@woosh/meep-engine 2.49.9 → 2.50.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 (170) hide show
  1. package/editor/actions/concrete/ArrayCopyAction.js +1 -1
  2. package/package.json +1 -1
  3. package/src/core/binary/BinaryBuffer.js +1 -1
  4. package/src/core/binary/BinaryBuffer.spec.js +128 -0
  5. package/src/core/binary/int32_to_binary_string.js +4 -1
  6. package/src/core/binary/int32_to_binary_string.spec.js +9 -0
  7. package/src/core/bvh2/BinaryNode.js +0 -30
  8. package/src/core/bvh2/binary/2/BinaryUint32BVH.js +1 -1
  9. package/src/core/bvh2/binary/IndexedBinaryBVH.js +1 -1
  10. package/src/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +1 -1
  11. package/src/core/bvh2/bvh3/query/compute_tight_near_far_clipping_planes.js +1 -1
  12. package/src/core/cache/Cache.js +31 -29
  13. package/src/core/cache/Cache.spec.js +4 -1
  14. package/src/core/collection/HashMap.js +1 -1
  15. package/src/core/collection/array/{copyArray.js → array_copy.js} +1 -24
  16. package/src/core/collection/array/array_copy_entire.js +21 -0
  17. package/src/core/collection/array/typed/typed_array_copy.js +1 -1
  18. package/src/core/collection/queue/Deque.d.ts +4 -0
  19. package/src/core/collection/queue/Deque.js +5 -7
  20. package/src/core/collection/queue/Deque.spec.js +107 -0
  21. package/src/core/collection/table/RowFirstTable.js +1 -1
  22. package/src/core/geom/2d/aabb/AABB2.d.ts +14 -0
  23. package/src/core/geom/2d/aabb/AABB2.js +9 -7
  24. package/src/core/geom/2d/aabb/AABB2.spec.js +100 -0
  25. package/src/core/geom/2d/aabb/aabb2_compute_center_from_multiple.spec.js +11 -0
  26. package/src/core/geom/2d/aabb/aabb2_compute_overlap.spec.js +56 -0
  27. package/src/core/geom/2d/aabb/aabb2_contains.spec.js +40 -0
  28. package/src/core/geom/2d/bvh/Node2.js +1 -1
  29. package/src/core/geom/2d/convex-hull/fixed_convex_hull_humus.js +1 -1
  30. package/src/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +1 -1
  31. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_2d.js +35 -0
  32. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_array_2d.js +51 -0
  33. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_2d.js +15 -0
  34. package/src/core/geom/2d/line/line_segment_compute_line_segment_intersection_vectors_array_2d.js +30 -0
  35. package/src/core/geom/2d/line/line_segment_line_segment_intersection_exists_2d.js +29 -0
  36. package/src/core/geom/3d/aabb/AABB3.d.ts +4 -0
  37. package/src/core/geom/3d/aabb/AABB3.spec.js +30 -0
  38. package/src/core/geom/3d/aabb/aabb3_detailed_volume_intersection.js +4 -4
  39. package/src/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +5 -5
  40. package/src/core/geom/3d/matrix/m4_make_translation.js +1 -1
  41. package/src/core/geom/3d/plane/is_point_within_planes.js +1 -1
  42. package/src/core/geom/3d/plane/lerp_planes_to_array.js +2 -0
  43. package/src/core/geom/3d/plane/{plane_computeConvex3PlaneIntersection.js → plane3_compute_convex_3_plane_intersection.js} +1 -1
  44. package/src/core/geom/3d/plane/{plane3_computeLineSegmentIntersection.js → plane3_compute_line_segment_intersection.js} +1 -1
  45. package/src/core/geom/3d/plane/{computePlanePlaneIntersection.js → plane3_compute_plane_intersection.js} +15 -11
  46. package/src/core/geom/3d/plane/{computePlaneLineIntersection.js → plane3_compute_ray_intersection.js} +5 -1
  47. package/src/core/geom/3d/plane/plane3_intersect_plane.js +14 -0
  48. package/src/core/geom/3d/plane/{plane_three_compute_convex3_plane_intersection.js → plane3_three_compute_convex_3_plane_intersection.js} +7 -4
  49. package/src/core/geom/3d/plane/planeRayIntersection.js +2 -2
  50. package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.js +1 -1
  51. package/src/core/geom/3d/tetrahedra/TetrahedralMesh.js +1 -1
  52. package/src/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.js +5 -5
  53. package/src/core/geom/3d/tetrahedra/compute_circumsphere.js +1 -1
  54. package/src/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.js +1 -1
  55. package/src/core/geom/3d/topology/bounds/computeTriangleClusterNormalBoundingCone.js +1 -1
  56. package/src/core/geom/3d/topology/expandConnectivityByLocality.js +1 -1
  57. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +1 -1
  58. package/src/core/geom/Quaternion.d.ts +11 -0
  59. package/src/core/geom/Quaternion.js +36 -27
  60. package/src/core/geom/Quaternion.spec.js +141 -0
  61. package/src/core/geom/Vector2.d.ts +5 -1
  62. package/src/core/geom/Vector2.js +24 -0
  63. package/src/core/geom/Vector3.d.ts +6 -0
  64. package/src/core/geom/Vector3.spec.js +60 -0
  65. package/src/core/graph/GraphUtils.js +4 -2
  66. package/src/core/graph/layout/CircleLayout.js +4 -2
  67. package/src/core/math/vector_nd_dot.js +16 -0
  68. package/src/core/math/{normalizeArrayVector.js → vector_nd_normalize.js} +3 -3
  69. package/src/core/math/{normalizeArrayVector.spec.js → vector_nd_normalize.spec.js} +3 -3
  70. package/src/core/process/PromiseWatcher.spec.js +1 -1
  71. package/src/engine/animation/curve/compression/downsample_float_array_curve_by_error.js +1 -1
  72. package/src/engine/ecs/EntityBlueprint.d.ts +14 -0
  73. package/src/engine/ecs/EntityBlueprint.js +2 -2
  74. package/src/engine/ecs/EntityBlueprint.spec.js +52 -0
  75. package/src/engine/ecs/EntityBuilder.js +8 -0
  76. package/src/engine/ecs/EntityManager.d.ts +1 -0
  77. package/src/engine/ecs/EntityManager.js +17 -213
  78. package/src/engine/ecs/EntityManager.spec.js +62 -1
  79. package/src/engine/ecs/System.js +8 -2
  80. package/src/engine/ecs/fow/FogOfWar.js +1 -1
  81. package/src/engine/ecs/guid/GUID.js +1 -1
  82. package/src/engine/ecs/terrain/ecs/splat/SplatMapping.js +1 -1
  83. package/src/engine/ecs/terrain/overlay/TerrainOverlay.js +1 -1
  84. package/src/engine/ecs/terrain/tiles/TerrainTile.js +1 -1
  85. package/src/engine/ecs/transform/Transform.d.ts +2 -0
  86. package/src/engine/ecs/transform/Transform.spec.js +63 -0
  87. package/src/engine/ecs/transform-attachment/TransformAttachment.d.ts +17 -1
  88. package/src/engine/ecs/transform-attachment/TransformAttachment.js +12 -2
  89. package/src/engine/ecs/transform-attachment/TransformAttachment.spec.js +103 -0
  90. package/src/engine/graphics/ecs/camera/Camera.js +2 -2
  91. package/src/engine/graphics/ecs/path/entity/EntityPath.js +1 -1
  92. package/src/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +1 -1
  93. package/src/engine/graphics/geometry/MikkT/GenerateTSpaces.js +1 -1
  94. package/src/engine/graphics/geometry/MikkT/m_getNormal.js +1 -1
  95. package/src/engine/graphics/geometry/MikkT/m_getTexCoord.js +1 -1
  96. package/src/engine/graphics/geometry/bvh/buffered/BVHGeometryRaycaster.js +1 -1
  97. package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.js +1 -1
  98. package/src/engine/graphics/geometry/optimization/merge/merge_geometry_hierarchy.js +1 -1
  99. package/src/engine/graphics/impostors/octahedral/util/build_cutout_from_atlas_by_alpha.js +1 -1
  100. package/src/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.js +1 -1
  101. package/src/engine/graphics/render/Lines.js +1 -1
  102. package/src/engine/graphics/render/buffer/simple-fx/taa/TemporalSupersamplingRenderPlugin.js +1 -1
  103. package/src/engine/graphics/render/forward_plus/LightManager.js +1 -1
  104. package/src/engine/graphics/render/forward_plus/computeFrustumCorners.js +10 -10
  105. package/src/engine/graphics/render/forward_plus/model/Decal.js +1 -1
  106. package/src/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +1 -1
  107. package/src/engine/graphics/render/gizmo/GizmoShapeRenderingInterface.js +1 -1
  108. package/src/engine/graphics/render/layers/RenderLayerUtils.js +3 -3
  109. package/src/engine/graphics/render/view/CameraView.js +1 -1
  110. package/src/engine/graphics/render/visibility/hiz/query/BatchOcclusionQuery.js +1 -1
  111. package/src/engine/graphics/render/webgpu/sample/MeshInstance.js +1 -1
  112. package/src/engine/graphics/sh3/LightProbeVolume.js +1 -1
  113. package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.js +1 -1
  114. package/src/engine/graphics/sh3/path_tracer/PathTracer.js +1 -1
  115. package/src/engine/graphics/sh3/path_tracer/make_sky_hosek.js +1 -1
  116. package/src/engine/graphics/sh3/prototypeSH3Probe.js +1 -1
  117. package/src/engine/graphics/texture/3d/scs3d_read_2d_slice.js +1 -1
  118. package/src/engine/graphics/texture/CanvasClone.js +5 -1
  119. package/src/engine/graphics/texture/sampler/Sampler2D.js +14 -75
  120. package/src/engine/graphics/texture/sampler/bicubic.js +19 -19
  121. package/src/engine/graphics/texture/sampler/convertSampler2D2DataURL.spec.js +10 -0
  122. package/src/engine/graphics/texture/sampler/copy_Sampler2D_channel_data.spec.js +90 -0
  123. package/src/engine/graphics/texture/sampler/differenceSampler.js +13 -8
  124. package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_Chamfer.js +140 -0
  125. package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_NaiveFlood.js +130 -0
  126. package/src/engine/graphics/texture/sampler/distance/computeUnsignedDistanceField.js +10 -0
  127. package/src/engine/graphics/texture/sampler/distance/computeUnsignedDistanceField.spec.js +183 -0
  128. package/src/engine/graphics/texture/sampler/distance/computeUnsignedDistanceField_Chamfer.js +133 -0
  129. package/src/engine/graphics/texture/sampler/filter/mitchell.js +4 -0
  130. package/src/engine/graphics/texture/sampler/loadSampler2D.js +5 -2
  131. package/src/engine/graphics/texture/sampler/resize/sampler2d_downsample_mipmap.js +8 -3
  132. package/src/engine/graphics/texture/sampler/resize/sampler2d_downsample_mipmap.spec.js +13 -0
  133. package/src/engine/graphics/texture/sampler/sampler2d_channel_compute_min_indices.js +58 -0
  134. package/src/engine/graphics/trail/TemporalPath.js +0 -36
  135. package/src/engine/intelligence/behavior/composite/ParallelBehavior.spec.js +12 -12
  136. package/src/engine/intelligence/behavior/composite/SequenceBehavior.spec.js +17 -0
  137. package/src/engine/intelligence/behavior/primitive/SucceedingBehavior.js +3 -1
  138. package/src/engine/knowledge/database/StaticKnowledgeDataTable.d.ts +7 -1
  139. package/src/engine/knowledge/database/StaticKnowledgeDataTable.spec.js +21 -0
  140. package/src/engine/knowledge/database/StaticKnowledgeDataTableDescriptor.d.ts +2 -2
  141. package/src/engine/logging/ConsoleLoggerBackend.js +4 -0
  142. package/src/engine/logging/VoidLoggerBackend.js +12 -0
  143. package/src/engine/navigation/ecs/components/computeCatmullRomSpline.js +1 -1
  144. package/src/engine/navigation/ecs/components/computeCatmullRomSplineUniformDistance.js +1 -1
  145. package/src/engine/physics/cannon/CannonJSPhysicsSystem.js +1 -1
  146. package/src/engine/save/GameStateLoader.js +1 -1
  147. package/src/engine/scene/Scene.d.ts +2 -0
  148. package/src/engine/scene/Scene.js +2 -2
  149. package/src/engine/scene/Scene.spec.js +20 -0
  150. package/src/engine/scene/SceneManager.d.ts +4 -0
  151. package/src/engine/scene/SceneManager.js +46 -23
  152. package/src/engine/scene/SceneManager.spec.js +131 -0
  153. package/src/engine/sound/material/detector/terrain/TerrainSoundMaterialSurfaceDetector.js +2 -2
  154. package/src/engine/ui/GUIEngine.js +1 -1
  155. package/src/generation/grid/GridData.js +8 -2
  156. package/src/generation/grid/GridData.spec.js +5 -0
  157. package/src/generation/grid/generation/util/buildUnsignedDistanceField.js +3 -1
  158. package/src/generation/markers/MarkerNode.js +2 -2
  159. package/src/generation/markers/actions/MarkerNodeActionEntityPlacement.js +1 -1
  160. package/src/generation/theme/AreaMask.js +3 -1
  161. package/src/view/elements/progress/RectangularPieProgressView.js +8 -6
  162. package/src/view/minimap/dom/MinimapCameraView.js +3 -3
  163. package/src/core/geom/2d/LineSegment2.js +0 -175
  164. package/src/core/geom/3d/plane/computePlaneRayIntersection.js +0 -55
  165. package/src/core/geom/Matrix4.js +0 -275
  166. package/src/engine/graphics/texture/sampler/distanceField.js +0 -411
  167. package/src/engine/graphics/texture/sampler/distanceField.spec.js +0 -184
  168. package/src/engine/physics/cannon/cannon.min.js +0 -27
  169. package/src/generation/grid/MarkerMatchCounter.js +0 -25
  170. /package/src/engine/physics/spring/{Spring.js → computeHookeForce.js} +0 -0
@@ -1,411 +0,0 @@
1
- import { BitSet } from "../../../../core/binary/BitSet.js";
2
- import { assert } from "../../../../core/assert.js";
3
- import { clamp } from "../../../../core/math/clamp.js";
4
- import { max2 } from "../../../../core/math/max2.js";
5
- import { min2 } from "../../../../core/math/min2.js";
6
-
7
- /**
8
- * Naive flood implementation of a distance field computation algorithm
9
- * @author Alex Goldring Dec 2018
10
- * @param {Sampler2D} source
11
- * @param {Sampler2D} destination
12
- * @param {number} emptyValue
13
- */
14
- export function computeSignedDistanceField_(source, destination, emptyValue) {
15
- assert.equal(source.itemSize, 1, `unsupported source.itemSize, expected 1, got '${source.itemSize}'`);
16
- assert.typeOf(emptyValue, 'number', 'emptyValue');
17
-
18
- let i, j;
19
-
20
- const distanceData = destination.data;
21
-
22
- const visited = new BitSet();
23
-
24
- const openSet = new BitSet();
25
-
26
- //use "flood" algorithm
27
-
28
- //mark all visible tiles as visited
29
- const samplerData = source.data;
30
- const totalCellCount = samplerData.length;
31
-
32
- function traverseNeighbours(index, visitor) {
33
- let i = index - (width + 1);
34
-
35
- const top = index > width;
36
- const bottom = index < (totalCellCount - width);
37
-
38
- const x = index % width;
39
-
40
- const left = x > 0;
41
- const right = x < width - 1;
42
-
43
- if (top) {
44
- if (left) {
45
- visitor(i);
46
- }
47
-
48
- visitor(i + 1);
49
-
50
- if (right) {
51
- visitor(i + 2);
52
- }
53
- }
54
-
55
- i += width;
56
-
57
- if (left) {
58
- visitor(i);
59
- }
60
-
61
- if (right) {
62
- visitor(i + 2);
63
- }
64
-
65
- i += width;
66
-
67
- if (bottom) {
68
- if (left) {
69
- visitor(i);
70
- }
71
-
72
- visitor(i + 1);
73
-
74
- if (right) {
75
- visitor(i + 2);
76
- }
77
- }
78
-
79
- }
80
-
81
- const width = destination.width;
82
-
83
- for (i = 0; i < totalCellCount; i++) {
84
- const sampleValue = samplerData[i];
85
- if (sampleValue !== emptyValue) {
86
- visited.set(i, true);
87
- //write distance data
88
- distanceData[i] = 0;
89
- } else {
90
- distanceData[i] = 255;
91
- }
92
- }
93
-
94
- //populate initial open set
95
- for (i = visited.nextSetBit(0); i !== -1; i = visited.nextSetBit(i + 1)) {
96
- j = 0;
97
- traverseNeighbours(i, function (neighbourIndex) {
98
- if (!visited.get(neighbourIndex)) {
99
- //increment number of not visited
100
- j++;
101
- }
102
- });
103
-
104
- if (j === 0) {
105
- //all neighbours are visited, we can safely ignore this cell
106
- } else {
107
- openSet.set(i, true);
108
- }
109
- }
110
-
111
- for (i = openSet.nextSetBit(0); i !== -1; i = openSet.nextSetBit(0)) {
112
- //remove from open set
113
- openSet.set(i, false);
114
-
115
- const value = distanceData[i];
116
-
117
- traverseNeighbours(i, function (neighbourIndex) {
118
- const neighbourValue = value + 1;
119
-
120
- if (visited.get(neighbourIndex)) {
121
- if (distanceData[neighbourIndex] <= neighbourValue) {
122
- return;
123
- }
124
- } else {
125
- visited.set(neighbourIndex, true);
126
- }
127
-
128
- distanceData[neighbourIndex] = neighbourValue;
129
- //add neighbour to open set
130
- openSet.set(neighbourIndex, true);
131
- });
132
- }
133
- }
134
-
135
- /**
136
- * @param {Sampler2D} source
137
- * @param {Sampler2D} distanceField
138
- * @param {number} emptyValue
139
- */
140
- export function computeUnsignedDistanceField(source, distanceField, emptyValue) {
141
- computeUnsignedDistanceField_Chamfer(source, distanceField, emptyValue, 1, 1, 255);
142
- }
143
-
144
- /**
145
- * algorithm proposed by Borgefors, Chamfer distance [J. ACM 15 (1968) 600, Comput. Vis. Graph. Image Process. 34 (1986) 344], h
146
- * @param {Sampler2D} source
147
- * @param {Sampler2D} distanceField
148
- * @param {number} emptyValue
149
- * @param {number} d1 distance between two adjacent pixels in either x or y direction
150
- * @param {number} d2 distance between two diagonally adjacent pixels
151
- * @param {number} maxD highest value that distance field can hold
152
- */
153
- export function computeUnsignedDistanceField_Chamfer(source, distanceField, emptyValue, d1, d2, maxD) {
154
- const sourceData = source.data;
155
- const distanceFieldData = distanceField.data;
156
-
157
- const width = source.width;
158
- const height = source.height;
159
-
160
- const maxX = width - 1;
161
- const maxY = height - 1;
162
-
163
- let x, y, i, v;
164
-
165
- //initialize distance field
166
- const dataSize = height * width;
167
- for (i = 0; i < dataSize; i++) {
168
- if (sourceData[i] !== emptyValue) {
169
- distanceFieldData[i] = 0;
170
- } else {
171
- distanceFieldData[i] = maxD;
172
- }
173
- }
174
-
175
- //first pass (forward)
176
- for (y = 0; y < height; y++) {
177
-
178
- const y_m1 = max2(y - 1, 0);
179
-
180
- const y_w = y * width;
181
-
182
- const y_m1_w = y_m1 * width;
183
-
184
- for (x = 0; x < width; x++) {
185
-
186
- i = y_w + x;
187
-
188
- v = distanceFieldData[i];
189
-
190
- const x_m1 = max2(x - 1, 0);
191
- const x_p1 = min2(x + 1, maxX);
192
-
193
- const v0_i = x_m1 + y_m1_w;
194
- const v0 = distanceFieldData[v0_i] + d2;
195
-
196
- if (v0 < v) {
197
- distanceFieldData[i] = v0;
198
- v = v0;
199
- }
200
-
201
- const v1_i = x + y_m1_w;
202
- const v1 = distanceFieldData[v1_i] + d1;
203
-
204
- if (v1 < v) {
205
- distanceFieldData[i] = v1;
206
- v = v1;
207
- }
208
-
209
- const v2_i = x_p1 + y_m1_w;
210
- const v2 = distanceFieldData[v2_i] + d2;
211
-
212
- if (v2 < v) {
213
- distanceFieldData[i] = v2;
214
- v = v2;
215
- }
216
-
217
- const v3_i = x_m1 + y_w;
218
- const v3 = distanceFieldData[v3_i] + d1;
219
-
220
- if (v3 < v) {
221
- distanceFieldData[i] = v3;
222
- }
223
- }
224
- }
225
-
226
- //second pass (backward)
227
- for (y = maxY; y >= 0; y--) {
228
- const y_w = y * width;
229
-
230
- const y_p1 = min2(y + 1, maxY);
231
- const y_p1_w = y_p1 * width;
232
-
233
- for (x = maxX; x >= 0; x--) {
234
- const x_p1 = min2(x + 1, maxX);
235
- const x_m1 = max2(x - 1, 0);
236
-
237
- i = y_w + x;
238
-
239
- v = distanceFieldData[i];
240
-
241
- const v0_i = x_p1 + y_w;
242
- const v0 = distanceFieldData[v0_i] + d1;
243
-
244
- if (v0 < v) {
245
- distanceFieldData[i] = v0;
246
- v = v0;
247
- }
248
-
249
- const v1_i = x_m1 + y_p1_w;
250
- const v1 = distanceFieldData[v1_i] + d2;
251
-
252
- if (v1 < v) {
253
- distanceFieldData[i] = v1;
254
- v = v1;
255
- }
256
-
257
- const v2_i = x + y_p1_w;
258
- const v2 = distanceFieldData[v2_i] + d1;
259
-
260
- if (v2 < v) {
261
- distanceFieldData[i] = v2;
262
- v = v2;
263
- }
264
-
265
- const v3_i = x_p1 + y_p1_w;
266
- const v3 = distanceFieldData[v3_i] + d2;
267
-
268
- if (v3 < v) {
269
- distanceFieldData[i] = v3;
270
- }
271
- }
272
- }
273
- }
274
-
275
- /**
276
- * algorithm proposed by Borgefors, Chamfer distance [J. ACM 15 (1968) 600, Comput. Vis. Graph. Image Process. 34 (1986) 344], h
277
- * @param {Sampler2D} source
278
- * @param {Sampler2D} distanceField
279
- * @param {number} emptyValue
280
- * @param {number} d1 distance between two adjacent pixels in either x or y direction
281
- * @param {number} d2 distance between two diagonally adjacent pixels
282
- * @param maxD
283
- */
284
- export function computeSignedDistanceField_Chamfer(source, distanceField, emptyValue, d1, d2, maxD) {
285
- const sourceData = source.data;
286
- const distanceFieldData = distanceField.data;
287
-
288
- const width = source.width;
289
- const height = source.height;
290
-
291
- const maxX = width - 1;
292
- const maxY = height - 1;
293
-
294
- function getS(x, y) {
295
- x = clamp(x, 0, maxX);
296
- y = clamp(y, 0, maxY);
297
-
298
- const index = x + y * width;
299
-
300
- return sourceData[index];
301
- }
302
-
303
- function getD(x, y) {
304
- x = clamp(x, 0, maxX);
305
- y = clamp(y, 0, maxY);
306
-
307
- const index = x + y * width;
308
-
309
- return distanceFieldData[index];
310
- }
311
-
312
- function setD(x, y, v) {
313
- x = clamp(x, 0, maxX);
314
- y = clamp(y, 0, maxY);
315
-
316
- const index = x + y * width;
317
-
318
- distanceFieldData[index] = min2(v, maxD);
319
- }
320
-
321
- let x, y;
322
-
323
- //initialize distance field
324
- for (y = 0; y < height; y++) {
325
- for (x = 0; x < width; x++) {
326
- if (
327
- getS(x - 1, y) !== getS(x, y)
328
- || getS(x + 1, y) !== getS(x, y)
329
- || getS(x, y - 1) !== getS(x, y)
330
- || getS(x, y + 1) !== getS(x, y)
331
- ) {
332
- setD(x, y, 0);
333
- } else {
334
- setD(x, y, 255);
335
- }
336
- }
337
- }
338
-
339
- //first pass (forward)
340
- for (y = 0; y < height; y++) {
341
- for (x = 0; x < width; x++) {
342
-
343
- const v = getD(x, y);
344
-
345
- const v0 = getD(x - 1, y - 1) + d2;
346
-
347
- if (v0 < v) {
348
- setD(x, y, v0);
349
- }
350
-
351
- const v1 = getD(x, y - 1) + d1;
352
-
353
- if (v1 < v) {
354
- setD(x, y, v1);
355
- }
356
-
357
- const v2 = getD(x + 1, y - 1) + d2;
358
-
359
- if (v2 < v) {
360
- setD(x, y, v2);
361
- }
362
-
363
- const v3 = getD(x - 1, y) + d1;
364
-
365
- if (v3 < v) {
366
- setD(x, y, v3);
367
- }
368
- }
369
- }
370
-
371
- //second pass (backward)
372
- for (y = maxY; y >= 0; y--) {
373
- for (x = maxX; x >= 0; x--) {
374
- const v = getD(x, y);
375
-
376
- const v0 = getD(x + 1, y) + d1;
377
-
378
- if (v0 < v) {
379
- setD(x, y, v0);
380
- }
381
-
382
- const v1 = getD(x - 1, y + 1) + d2;
383
-
384
- if (v1 < v) {
385
- setD(x, y, v1);
386
- }
387
-
388
- const v2 = getD(x, y + 1) + d1;
389
-
390
- if (v2 < v) {
391
- setD(x, y, v2);
392
- }
393
-
394
- const v3 = getD(x + 1, y + 1) + d2;
395
-
396
- if (v3 < v) {
397
- setD(x, y, v3);
398
- }
399
- }
400
- }
401
-
402
- //indicate inside & outside
403
- for (y = 0; y < height; y++) {
404
- for (x = 0; x < width; x++) {
405
- if (getS(x, y) !== emptyValue) {
406
- //inside
407
- setD(x, y, -getD(x, y));
408
- }
409
- }
410
- }
411
- }
@@ -1,184 +0,0 @@
1
- import { seededRandom } from "../../../../core/math/random/seededRandom.js";
2
- import { Sampler2D } from "./Sampler2D.js";
3
- import { computeUnsignedDistanceField } from "./distanceField.js";
4
- import { randomIntegerBetween } from "../../../../core/math/random/randomIntegerBetween.js";
5
-
6
- describe('computeUnsignedDistanceField', () => {
7
- test('empty', () => {
8
- const source = Sampler2D.uint8(1, 0, 0);
9
- const target = Sampler2D.uint8(1, 0, 0);
10
-
11
- computeUnsignedDistanceField(source, target, 0);
12
- });
13
-
14
- test('1 pixel empty source', () => {
15
- const source = Sampler2D.uint8(1, 1, 1);
16
- const target = Sampler2D.uint8(1, 1, 1);
17
-
18
- computeUnsignedDistanceField(source, target, 0);
19
-
20
- expect(target.readChannel(0,0,0)).toBe(255);
21
- });
22
-
23
- test('1 pixel filled source', () => {
24
- const source = Sampler2D.uint8(1, 1, 1);
25
- source.set(0, 0, [255]);
26
-
27
- const target = Sampler2D.uint8(1, 1, 1);
28
-
29
- computeUnsignedDistanceField(source, target, 0);
30
-
31
- expect(target.readChannel(0,0,0)).toBe(0);
32
- });
33
-
34
- test('3x3 pixel source with filled middle', () => {
35
- const source = Sampler2D.uint8(1, 3, 3);
36
- source.set(1, 1, [255]);
37
-
38
- const target = Sampler2D.uint8(1, 3, 3);
39
-
40
- computeUnsignedDistanceField(source, target, 0);
41
-
42
- expect(target.readChannel(0, 0,0)).toBe(1);
43
- expect(target.readChannel(1, 0,0)).toBe(1);
44
- expect(target.readChannel(2,0,0)).toBe(1);
45
-
46
- expect(target.readChannel(0,1,0)).toBe(1);
47
- expect(target.readChannel(1,1,0)).toBe(0);
48
- expect(target.readChannel(2,1,0)).toBe(1);
49
-
50
- expect(target.readChannel(0,2,0)).toBe(1);
51
- expect(target.readChannel(1,2,0)).toBe(1);
52
- expect(target.readChannel(2,2,0)).toBe(1);
53
- });
54
-
55
- test('3x3 pixel source with empty middle', () => {
56
- const source = Sampler2D.uint8(1, 3, 3);
57
- source.data.fill(255);
58
- source.set(1, 1, [0]);
59
-
60
- const target = Sampler2D.uint8(1, 3, 3);
61
-
62
- computeUnsignedDistanceField(source, target, 0);
63
-
64
- expect(target.readChannel(0,0,0)).toBe(0);
65
- expect(target.readChannel(1,0,0)).toBe(0);
66
- expect(target.readChannel(2,0,0)).toBe(0);
67
-
68
- expect(target.readChannel(0,1,0)).toBe(0);
69
- expect(target.readChannel(1,1,0)).toBe(1);
70
- expect(target.readChannel(2,1,0)).toBe(0);
71
-
72
- expect(target.readChannel(0,2,0)).toBe(0);
73
- expect(target.readChannel(1,2,0)).toBe(0);
74
- expect(target.readChannel(2,2,0)).toBe(0);
75
- });
76
-
77
- test('3x3 pixel source with empty corners', () => {
78
- const source = Sampler2D.uint8(1, 3, 3);
79
- source.data.fill(255);
80
- source.set(0, 0, [0]);
81
- source.set(2, 0, [0]);
82
- source.set(0, 2, [0]);
83
- source.set(2, 2, [0]);
84
-
85
- const target = Sampler2D.uint8(1, 3, 3);
86
-
87
- computeUnsignedDistanceField(source, target, 0);
88
-
89
- expect(target.readChannel(0,0,0)).toBe(1);
90
- expect(target.readChannel(1,0,0)).toBe(0);
91
- expect(target.readChannel(2,0,0)).toBe(1);
92
-
93
- expect(target.readChannel(0,1,0)).toBe(0);
94
- expect(target.readChannel(1,1,0)).toBe(0);
95
- expect(target.readChannel(2,1,0)).toBe(0);
96
-
97
- expect(target.readChannel(0,2,0)).toBe(1);
98
- expect(target.readChannel(1,2,0)).toBe(0);
99
- expect(target.readChannel(2,2,0)).toBe(1);
100
- });
101
-
102
- test('3x3 pixel source with filled corners', () => {
103
- const source = Sampler2D.uint8(1, 3, 3);
104
- source.data.fill(0);
105
- source.set(0, 0, [255]);
106
- source.set(2, 0, [255]);
107
- source.set(0, 2, [255]);
108
- source.set(2, 2, [255]);
109
-
110
- const target = Sampler2D.uint8(1, 3, 3);
111
-
112
- computeUnsignedDistanceField(source, target, 0);
113
-
114
- expect(target.readChannel(0,0,0)).toBe(0);
115
- expect(target.readChannel(1,0,0)).toBe(1);
116
- expect(target.readChannel(2,0,0)).toBe(0);
117
-
118
- expect(target.readChannel(0,1,0)).toBe(1);
119
- expect(target.readChannel(1,1,0)).toBe(1);
120
- expect(target.readChannel(2,1,0)).toBe(1);
121
-
122
- expect(target.readChannel(0,2,0)).toBe(0);
123
- expect(target.readChannel(1,2,0)).toBe(1);
124
- expect(target.readChannel(2,2,0)).toBe(0);
125
- });
126
-
127
- test('3x1 pixel source with 1 filled corner', () => {
128
- const source = Sampler2D.uint8(1, 3, 1);
129
- source.data.fill(0);
130
- source.set(0, 0, [255]);
131
-
132
- const target = Sampler2D.uint8(1, 3, 1);
133
-
134
- computeUnsignedDistanceField(source, target, 0);
135
-
136
- expect(target.readChannel(0,0,0)).toBe(0);
137
- expect(target.readChannel(1,0,0)).toBe(1);
138
- expect(target.readChannel(2,0,0)).toBe(2);
139
- });
140
-
141
- test('3x3 pixel source with 1 filled corner', () => {
142
- const source = Sampler2D.uint8(1, 3, 3);
143
- source.data.fill(0);
144
- source.set(0, 0, [255]);
145
-
146
- const target = Sampler2D.uint8(1, 3, 3);
147
-
148
- computeUnsignedDistanceField(source, target, 0);
149
-
150
- expect(target.readChannel(0,0,0)).toBe(0);
151
- expect(target.readChannel(1,0,0)).toBe(1);
152
- expect(target.readChannel(2,0,0)).toBe(2);
153
-
154
- expect(target.readChannel(0,1,0)).toBe(1);
155
- expect(target.readChannel(1,1,0)).toBe(1);
156
- expect(target.readChannel(2,1,0)).toBe(2);
157
-
158
- expect(target.readChannel(0,2,0)).toBe(2);
159
- expect(target.readChannel(1,2,0)).toBe(2);
160
- expect(target.readChannel(2,2,0)).toBe(2);
161
- });
162
-
163
- test('performance', () => {
164
- const sizeX = 100;
165
- const sizeY = 100;
166
-
167
- const source = Sampler2D.uint8(1, sizeX, sizeY);
168
-
169
- const random = seededRandom(42);
170
- source.data.fill(0);
171
- for (let i = 0; i < source.data.length * 0.1; i++) {
172
- const x = randomIntegerBetween(random, 0, sizeX);
173
- const y = randomIntegerBetween(random, 0, sizeY);
174
- source.set(x, y, [255]);
175
- }
176
-
177
- const target = Sampler2D.uint8(1, sizeX, sizeY);
178
-
179
- console.time('p');
180
- computeUnsignedDistanceField(source, target, 0);
181
- console.timeEnd('p');
182
-
183
- });
184
- });