@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
@@ -3,7 +3,7 @@ import {
3
3
  sky_hosek_precompute
4
4
  } from "../sky/hosek/sky_hosek_compute_irradiance_by_direction.js";
5
5
  import { vec3 } from "gl-matrix";
6
- import { array_copy } from "../../../../core/collection/array/copyArray.js";
6
+ import { array_copy } from "../../../../core/collection/array/array_copy.js";
7
7
  import { max2 } from "../../../../core/math/max2.js";
8
8
 
9
9
  export function make_sky_hosek(sun = [0, 1, 0], turbidity = 1, overcast = 0, albedo = [0, 0, 0]) {
@@ -19,7 +19,7 @@ import { Transform } from "../../ecs/transform/Transform.js";
19
19
  import Vector3 from "../../../core/geom/Vector3.js";
20
20
  import { BinaryBuffer } from "../../../core/binary/BinaryBuffer.js";
21
21
  import { is_typed_array_equals } from "../../../core/collection/array/typed/is_typed_array_equals.js";
22
- import { array_copy } from "../../../core/collection/array/copyArray.js";
22
+ import { array_copy } from "../../../core/collection/array/array_copy.js";
23
23
  import { randomFloatBetween } from "../../../core/math/random/randomFloatBetween.js";
24
24
  import { GLTFAssetLoader } from "../../asset/loaders/GLTFAssetLoader.js";
25
25
  import { three_object_to_entity_composition } from "../ecs/mesh-v2/three_object_to_entity_composition.js";
@@ -1,4 +1,4 @@
1
- import { array_copy } from "../../../../core/collection/array/copyArray.js";
1
+ import { array_copy } from "../../../../core/collection/array/array_copy.js";
2
2
 
3
3
  /**
4
4
  *
@@ -3,7 +3,11 @@
3
3
  */
4
4
 
5
5
 
6
-
6
+ /**
7
+ *
8
+ * @param {HTMLCanvasElement} oldCanvas
9
+ * @return {HTMLCanvasElement}
10
+ */
7
11
  function cloneCanvas(oldCanvas) {
8
12
 
9
13
  //create a new canvas
@@ -92,50 +92,14 @@ export class Sampler2D {
92
92
  }
93
93
 
94
94
  /**
95
+ * @deprecated
95
96
  * @param {number[]} result
97
+ * @param {number} result_offset
96
98
  * @param {number} [channel=0]
99
+ * @returns {number} number of matches written to result array
97
100
  */
98
- computeMinIndices(result, channel = 0) {
99
- const itemSize = this.itemSize;
100
-
101
- assert.typeOf(channel, "number", "channel");
102
- assert.ok(channel >= 0, `channel must be >= 0, was ${channel}`);
103
- assert.ok(channel < itemSize, `channel must be less than itemSize(=${itemSize}), was ${channel}`);
104
-
105
- assert.ok(Array.isArray(result), "result is not an array");
106
-
107
- const data = this.data;
108
-
109
- const l = data.length;
110
-
111
- if (l === 0) {
112
- //no data
113
- return;
114
- }
115
-
116
- let bestValue = data[channel];
117
-
118
- let resultCount = 0;
119
-
120
- for (let i = channel + itemSize; i < l; i += itemSize) {
121
- const value = data[i];
122
-
123
- if (bestValue > value) {
124
- bestValue = value;
125
- //drop result
126
- resultCount = 1;
127
-
128
- result[0] = i;
129
- } else if (value === bestValue) {
130
- result[resultCount++] = i;
131
- }
132
-
133
- }
134
-
135
- //crop results
136
- if (resultCount < result.length) {
137
- result.splice(resultCount, result.length - resultCount);
138
- }
101
+ computeMinIndices(result, result_offset = 0, channel = 0) {
102
+ throw new Error("deprecated, use sampler2d_channel_compute_min_indices")
139
103
  }
140
104
 
141
105
  /**
@@ -410,7 +374,7 @@ export class Sampler2D {
410
374
  *
411
375
  * @param {number} x
412
376
  * @param {number} y
413
- * @param {number[]} result
377
+ * @param {number[]|Float32Array|Float64Array} result
414
378
  * @param {number} result_offset
415
379
  */
416
380
  sampleBilinear(x, y, result, result_offset = 0) {
@@ -446,6 +410,12 @@ export class Sampler2D {
446
410
  * @returns {number}
447
411
  */
448
412
  sampleChannelBilinear(x, y, channel) {
413
+ assert.isNumber(x, 'x');
414
+ assert.notNaN(x, 'x');
415
+
416
+ assert.isNumber(y, 'y');
417
+ assert.notNaN(y, 'y');
418
+
449
419
  assert.isNonNegativeInteger(channel, 'channel');
450
420
 
451
421
  const itemSize = this.itemSize;
@@ -548,6 +518,7 @@ export class Sampler2D {
548
518
  assert.isNumber(channel, "channel");
549
519
 
550
520
  assert.isNonNegativeInteger(channel, 'channel');
521
+ assert.lessThanOrEqual(channel, this.itemSize);
551
522
 
552
523
  const index = (y * this.width + x) * this.itemSize + channel;
553
524
 
@@ -933,6 +904,7 @@ export class Sampler2D {
933
904
 
934
905
  /**
935
906
  * Fill data values with zeros for a given area
907
+ * Specialized version of `fill` method, optimized for speed
936
908
  * @param {Number} x
937
909
  * @param {Number} y
938
910
  * @param {Number} width
@@ -1205,39 +1177,6 @@ export class Sampler2D {
1205
1177
  throw new Error('Deprecated, use Sampler2DSerializationAdapter instead');
1206
1178
  }
1207
1179
 
1208
- /**
1209
- *
1210
- * @param {number} x
1211
- * @param {number} y
1212
- * @param {function(x:number, y:number, value:number, index:number):boolean?} visitor
1213
- * @param {*} [thisArg]
1214
- */
1215
- traverseOrthogonalNeighbours(x, y, visitor, thisArg) {
1216
- const width = this.width;
1217
- const height = this.height;
1218
-
1219
- const index = this.point2index(x, y);
1220
-
1221
- let i = 0;
1222
- const data = this.data;
1223
- if (x > 0) {
1224
- i = index - 1;
1225
- visitor.call(thisArg, x - 1, y, data[i], i);
1226
- }
1227
- if (x < width - 1) {
1228
- i = index + 1;
1229
- visitor.call(thisArg, x + 1, y, data[i], i);
1230
- }
1231
- if (y > 0) {
1232
- i = index - width;
1233
- visitor.call(thisArg, x, y - 1, data[i], i);
1234
- }
1235
- if (y < height - 1) {
1236
- i = index + width;
1237
- visitor.call(thisArg, x, y + 1, data[i], i);
1238
- }
1239
- }
1240
-
1241
1180
  /**
1242
1181
  *
1243
1182
  * @param {Sampler2D} other
@@ -1,24 +1,24 @@
1
1
  /**
2
2
  * @see https://github.com/hughsk/bicubic/blob/master/index.js
3
- * @param xf
4
- * @param yf
5
- * @param p00
6
- * @param p01
7
- * @param p02
8
- * @param p03
9
- * @param p10
10
- * @param p11
11
- * @param p12
12
- * @param p13
13
- * @param p20
14
- * @param p21
15
- * @param p22
16
- * @param p23
17
- * @param p30
18
- * @param p31
19
- * @param p32
20
- * @param p33
21
- * @returns {*}
3
+ * @param {number} xf
4
+ * @param {number} yf
5
+ * @param {number} p00
6
+ * @param {number} p01
7
+ * @param {number} p02
8
+ * @param {number} p03
9
+ * @param {number} p10
10
+ * @param {number} p11
11
+ * @param {number} p12
12
+ * @param {number} p13
13
+ * @param {number} p20
14
+ * @param {number} p21
15
+ * @param {number} p22
16
+ * @param {number} p23
17
+ * @param {number} p30
18
+ * @param {number} p31
19
+ * @param {number} p32
20
+ * @param {number} p33
21
+ * @returns {number}
22
22
  */
23
23
  export function bicubic(
24
24
  xf, yf
@@ -0,0 +1,10 @@
1
+ import { convertSampler2D2DataURL } from "./convertSampler2D2DataURL.js";
2
+ import { Sampler2D } from "./Sampler2D.js";
3
+
4
+ // currently does not run in Node.js context due to reliance on HTMLCanvasElement that is absent in Node.js
5
+ test.skip("result is a data URL", () => {
6
+ const result = convertSampler2D2DataURL(Sampler2D.uint8(4, 1, 1));
7
+
8
+ expect(typeof result).toBe('string');
9
+ expect(result.startsWith("data://")).toBe(true);
10
+ });
@@ -0,0 +1,90 @@
1
+ import { copy_Sampler2D_channel_data } from "./copy_Sampler2D_channel_data.js";
2
+ import { Sampler2D } from "./Sampler2D.js";
3
+
4
+ test("should throw when dimensions do not match", () => {
5
+ expect(() => copy_Sampler2D_channel_data(
6
+ Sampler2D.uint8(1, 1, 1),
7
+ Sampler2D.uint8(1, 2, 1),
8
+ )).toThrow();
9
+
10
+ expect(() => copy_Sampler2D_channel_data(
11
+ Sampler2D.uint8(1, 2, 1),
12
+ Sampler2D.uint8(1, 1, 1),
13
+ )).toThrow();
14
+
15
+ expect(() => copy_Sampler2D_channel_data(
16
+ Sampler2D.uint8(1, 1, 2),
17
+ Sampler2D.uint8(1, 1, 1),
18
+ )).toThrow();
19
+
20
+ expect(() => copy_Sampler2D_channel_data(
21
+ Sampler2D.uint8(1, 1, 1),
22
+ Sampler2D.uint8(1, 1, 2),
23
+ )).toThrow();
24
+
25
+ expect(() => copy_Sampler2D_channel_data(
26
+ Sampler2D.uint8(1, 2, 2),
27
+ Sampler2D.uint8(1, 1, 1),
28
+ )).toThrow();
29
+
30
+ expect(() => copy_Sampler2D_channel_data(
31
+ Sampler2D.uint8(1, 1, 1),
32
+ Sampler2D.uint8(1, 2, 2),
33
+ )).toThrow();
34
+ });
35
+
36
+ test("channel counts match", () => {
37
+ const source = Sampler2D.uint8(1, 1, 1);
38
+ source.writeChannel(0, 0, 0, 7);
39
+
40
+ const target = Sampler2D.uint8(1, 1, 1);
41
+
42
+ copy_Sampler2D_channel_data(source, target);
43
+
44
+ expect(target.readChannel(0, 0, 0)).toEqual(7);
45
+ });
46
+
47
+ test("from 2 channels to 1", () => {
48
+
49
+ const source = Sampler2D.uint8(2, 1, 1);
50
+ source.writeChannel(0, 0, 0, 7);
51
+ source.writeChannel(0, 0, 1, 13);
52
+
53
+ const target = Sampler2D.uint8(1, 1, 1);
54
+
55
+ copy_Sampler2D_channel_data(source, target);
56
+
57
+ expect(target.readChannel(0, 0, 0)).toEqual(7);
58
+ });
59
+
60
+ test("from 3 channels to 4", () => {
61
+
62
+ const source = Sampler2D.uint8(3, 1, 1);
63
+ source.set(0, 0, [3, 7, 13]);
64
+
65
+ const target = Sampler2D.uint8(4, 1, 1);
66
+
67
+ copy_Sampler2D_channel_data(source, target);
68
+
69
+ const sample = [];
70
+
71
+ target.read(0, 0, sample);
72
+
73
+ expect(sample).toEqual([3, 7, 13, 255]);
74
+ });
75
+
76
+ test("from 2 channels to 4", () => {
77
+
78
+ const source = Sampler2D.uint8(2, 1, 1);
79
+ source.set(0, 0, [3, 7]);
80
+
81
+ const target = Sampler2D.uint8(4, 1, 1);
82
+
83
+ copy_Sampler2D_channel_data(source, target);
84
+
85
+ const sample = [];
86
+
87
+ target.read(0, 0, sample);
88
+
89
+ expect(sample).toEqual([3, 3, 3, 7]);
90
+ });
@@ -1,5 +1,6 @@
1
- import Vector4 from "../../../../core/geom/Vector4.js";
2
1
  import { Sampler2D } from "./Sampler2D.js";
2
+ import { vector_nd_normalize } from "../../../../core/math/vector_nd_normalize.js";
3
+ import { vector_nd_dot } from "../../../../core/math/vector_nd_dot.js";
3
4
 
4
5
  /**
5
6
  *
@@ -8,8 +9,10 @@ import { Sampler2D } from "./Sampler2D.js";
8
9
  * @returns {Sampler2D}
9
10
  */
10
11
  export function differenceSampler(sampler0, sampler1) {
11
- let v0 = new Vector4();
12
- let v1 = new Vector4();
12
+ const dimension_count = sampler0.itemSize;
13
+
14
+ const v0 = new Float64Array(dimension_count);
15
+ const v1 = new Float64Array(dimension_count);
13
16
  //
14
17
  const width = sampler0.width;
15
18
  const height = sampler0.height;
@@ -17,12 +20,14 @@ export function differenceSampler(sampler0, sampler1) {
17
20
  const difference = new Float32Array(width * height);
18
21
  for (let y = 0; y < height; y++) {
19
22
  for (let x = 0; x < width; x++) {
20
- v0 = sampler0.get(x, y, v0);
21
- v1 = sampler1.get(x, y, v1);
22
- v0.normalize();
23
- v1.normalize();
23
+ sampler0.sampleBilinear(x, y, v0);
24
+ sampler1.sampleBilinear(x, y, v1);
25
+
26
+ vector_nd_normalize(v0, v0, dimension_count);
27
+ vector_nd_normalize(v1, v1, dimension_count);
28
+
24
29
  //check distance
25
- difference[x + y * width] = 1 - v0.dot(v1);
30
+ difference[x + y * width] = 1 - vector_nd_dot(v0, v1, dimension_count);
26
31
  }
27
32
  }
28
33
  //
@@ -0,0 +1,140 @@
1
+ import { clamp } from "../../../../../core/math/clamp.js";
2
+ import { min2 } from "../../../../../core/math/min2.js";
3
+
4
+ /**
5
+ * algorithm proposed by Borgefors, Chamfer distance [J. ACM 15 (1968) 600, Comput. Vis. Graph. Image Process. 34 (1986) 344], h
6
+ * @param {Sampler2D} source
7
+ * @param {Sampler2D} distanceField
8
+ * @param {number} emptyValue
9
+ * @param {number} d1 distance between two adjacent pixels in either x or y direction
10
+ * @param {number} d2 distance between two diagonally adjacent pixels
11
+ * @param maxD
12
+ */
13
+ export function computeSignedDistanceField_Chamfer(source, distanceField, emptyValue, d1, d2, maxD) {
14
+ const sourceData = source.data;
15
+ const distanceFieldData = distanceField.data;
16
+
17
+ const width = source.width;
18
+ const height = source.height;
19
+
20
+ const maxX = width - 1;
21
+ const maxY = height - 1;
22
+
23
+ function getS(x, y) {
24
+ x = clamp(x, 0, maxX);
25
+ y = clamp(y, 0, maxY);
26
+
27
+ const index = x + y * width;
28
+
29
+ return sourceData[index];
30
+ }
31
+
32
+ function getD(x, y) {
33
+ x = clamp(x, 0, maxX);
34
+ y = clamp(y, 0, maxY);
35
+
36
+ const index = x + y * width;
37
+
38
+ return distanceFieldData[index];
39
+ }
40
+
41
+ function setD(x, y, v) {
42
+ x = clamp(x, 0, maxX);
43
+ y = clamp(y, 0, maxY);
44
+
45
+ const index = x + y * width;
46
+
47
+ distanceFieldData[index] = min2(v, maxD);
48
+ }
49
+
50
+ let x, y;
51
+
52
+ //initialize distance field
53
+ for (y = 0; y < height; y++) {
54
+ for (x = 0; x < width; x++) {
55
+ if (
56
+ getS(x - 1, y) !== getS(x, y)
57
+ || getS(x + 1, y) !== getS(x, y)
58
+ || getS(x, y - 1) !== getS(x, y)
59
+ || getS(x, y + 1) !== getS(x, y)
60
+ ) {
61
+ setD(x, y, 0);
62
+ } else {
63
+ setD(x, y, 255);
64
+ }
65
+ }
66
+ }
67
+
68
+ //first pass (forward)
69
+ for (y = 0; y < height; y++) {
70
+ for (x = 0; x < width; x++) {
71
+
72
+ const v = getD(x, y);
73
+
74
+ const v0 = getD(x - 1, y - 1) + d2;
75
+
76
+ if (v0 < v) {
77
+ setD(x, y, v0);
78
+ }
79
+
80
+ const v1 = getD(x, y - 1) + d1;
81
+
82
+ if (v1 < v) {
83
+ setD(x, y, v1);
84
+ }
85
+
86
+ const v2 = getD(x + 1, y - 1) + d2;
87
+
88
+ if (v2 < v) {
89
+ setD(x, y, v2);
90
+ }
91
+
92
+ const v3 = getD(x - 1, y) + d1;
93
+
94
+ if (v3 < v) {
95
+ setD(x, y, v3);
96
+ }
97
+ }
98
+ }
99
+
100
+ //second pass (backward)
101
+ for (y = maxY; y >= 0; y--) {
102
+ for (x = maxX; x >= 0; x--) {
103
+ const v = getD(x, y);
104
+
105
+ const v0 = getD(x + 1, y) + d1;
106
+
107
+ if (v0 < v) {
108
+ setD(x, y, v0);
109
+ }
110
+
111
+ const v1 = getD(x - 1, y + 1) + d2;
112
+
113
+ if (v1 < v) {
114
+ setD(x, y, v1);
115
+ }
116
+
117
+ const v2 = getD(x, y + 1) + d1;
118
+
119
+ if (v2 < v) {
120
+ setD(x, y, v2);
121
+ }
122
+
123
+ const v3 = getD(x + 1, y + 1) + d2;
124
+
125
+ if (v3 < v) {
126
+ setD(x, y, v3);
127
+ }
128
+ }
129
+ }
130
+
131
+ //indicate inside & outside
132
+ for (y = 0; y < height; y++) {
133
+ for (x = 0; x < width; x++) {
134
+ if (getS(x, y) !== emptyValue) {
135
+ //inside
136
+ setD(x, y, -getD(x, y));
137
+ }
138
+ }
139
+ }
140
+ }
@@ -0,0 +1,130 @@
1
+ import { assert } from "../../../../../core/assert.js";
2
+ import { BitSet } from "../../../../../core/binary/BitSet.js";
3
+
4
+ /**
5
+ * Naive flood implementation of a distance field computation algorithm
6
+ * @author Alex Goldring Dec 2018
7
+ * @param {Sampler2D} source
8
+ * @param {Sampler2D} destination
9
+ * @param {number} emptyValue
10
+ */
11
+ export function computeSignedDistanceField_NaiveFlood(source, destination, emptyValue) {
12
+ assert.equal(source.itemSize, 1, `unsupported source.itemSize, expected 1, got '${source.itemSize}'`);
13
+ assert.typeOf(emptyValue, 'number', 'emptyValue');
14
+
15
+ let i, j;
16
+
17
+ const distanceData = destination.data;
18
+
19
+ const visited = new BitSet();
20
+
21
+ const openSet = new BitSet();
22
+
23
+ //use "flood" algorithm
24
+
25
+ //mark all visible tiles as visited
26
+ const samplerData = source.data;
27
+ const totalCellCount = samplerData.length;
28
+
29
+ function traverseNeighbours(index, visitor) {
30
+ let i = index - (width + 1);
31
+
32
+ const top = index > width;
33
+ const bottom = index < (totalCellCount - width);
34
+
35
+ const x = index % width;
36
+
37
+ const left = x > 0;
38
+ const right = x < width - 1;
39
+
40
+ if (top) {
41
+ if (left) {
42
+ visitor(i);
43
+ }
44
+
45
+ visitor(i + 1);
46
+
47
+ if (right) {
48
+ visitor(i + 2);
49
+ }
50
+ }
51
+
52
+ i += width;
53
+
54
+ if (left) {
55
+ visitor(i);
56
+ }
57
+
58
+ if (right) {
59
+ visitor(i + 2);
60
+ }
61
+
62
+ i += width;
63
+
64
+ if (bottom) {
65
+ if (left) {
66
+ visitor(i);
67
+ }
68
+
69
+ visitor(i + 1);
70
+
71
+ if (right) {
72
+ visitor(i + 2);
73
+ }
74
+ }
75
+
76
+ }
77
+
78
+ const width = destination.width;
79
+
80
+ for (i = 0; i < totalCellCount; i++) {
81
+ const sampleValue = samplerData[i];
82
+ if (sampleValue !== emptyValue) {
83
+ visited.set(i, true);
84
+ //write distance data
85
+ distanceData[i] = 0;
86
+ } else {
87
+ distanceData[i] = 255;
88
+ }
89
+ }
90
+
91
+ //populate initial open set
92
+ for (i = visited.nextSetBit(0); i !== -1; i = visited.nextSetBit(i + 1)) {
93
+ j = 0;
94
+ traverseNeighbours(i, function (neighbourIndex) {
95
+ if (!visited.get(neighbourIndex)) {
96
+ //increment number of not visited
97
+ j++;
98
+ }
99
+ });
100
+
101
+ if (j === 0) {
102
+ //all neighbours are visited, we can safely ignore this cell
103
+ } else {
104
+ openSet.set(i, true);
105
+ }
106
+ }
107
+
108
+ for (i = openSet.nextSetBit(0); i !== -1; i = openSet.nextSetBit(0)) {
109
+ //remove from open set
110
+ openSet.set(i, false);
111
+
112
+ const value = distanceData[i];
113
+
114
+ traverseNeighbours(i, function (neighbourIndex) {
115
+ const neighbourValue = value + 1;
116
+
117
+ if (visited.get(neighbourIndex)) {
118
+ if (distanceData[neighbourIndex] <= neighbourValue) {
119
+ return;
120
+ }
121
+ } else {
122
+ visited.set(neighbourIndex, true);
123
+ }
124
+
125
+ distanceData[neighbourIndex] = neighbourValue;
126
+ //add neighbour to open set
127
+ openSet.set(neighbourIndex, true);
128
+ });
129
+ }
130
+ }
@@ -0,0 +1,10 @@
1
+ import { computeUnsignedDistanceField_Chamfer } from "./computeUnsignedDistanceField_Chamfer.js";
2
+
3
+ /**
4
+ * @param {Sampler2D} source
5
+ * @param {Sampler2D} distanceField
6
+ * @param {number} emptyValue
7
+ */
8
+ export function computeUnsignedDistanceField(source, distanceField, emptyValue) {
9
+ computeUnsignedDistanceField_Chamfer(source, distanceField, emptyValue, 1, 1, 255);
10
+ }