@woosh/meep-engine 2.37.19 → 2.37.20

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 (110) hide show
  1. package/core/binary/float2uint8.js +8 -0
  2. package/core/binary/uint82float.js +8 -0
  3. package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +6 -4
  4. package/core/collection/list/List.d.ts +1 -1
  5. package/core/color/Color.js +69 -1
  6. package/core/color/YCbCr_to_rgb_uint24.js +3 -4
  7. package/core/color/hsv2rgb.js +4 -3
  8. package/core/color/linear_to_sRGB.js +4 -5
  9. package/core/color/rgb2uint24.js +6 -4
  10. package/core/color/rgb_to_YCbCr_uint24.js +11 -13
  11. package/core/events/signal/Signal.d.ts +11 -9
  12. package/core/geom/2d/quad-tree/qt_collect_by_circle.js +67 -0
  13. package/core/geom/Quaternion.d.ts +16 -1
  14. package/core/geom/Quaternion.js +129 -65
  15. package/core/geom/Quaternion.spec.js +24 -0
  16. package/core/geom/Vector2.js +3 -3
  17. package/core/geom/Vector3.d.ts +2 -0
  18. package/core/geom/Vector3.js +31 -7
  19. package/core/geom/Vector4.js +16 -0
  20. package/core/math/bell_membership_function.js +19 -0
  21. package/core/math/exp2.js +8 -0
  22. package/core/math/interval/NumericInterval.js +17 -0
  23. package/core/math/physics/brdf/brdf_burley.js +25 -0
  24. package/core/math/physics/bsdf/bsdf_schlick.js +22 -0
  25. package/core/math/physics/irradiance/interpolate_irradiance_linear.js +18 -0
  26. package/{engine/sound/ecs/emitter/attenuate/attenuateSoundLogarithmic.js → core/math/physics/irradiance/interpolate_irradiance_lograrithmic.js} +2 -2
  27. package/{engine/sound/ecs/emitter/attenuate/attenuateSoundSmith.js → core/math/physics/irradiance/interpolate_irradiance_smith.js} +1 -1
  28. package/editor/actions/concrete/ModifyPatchSampler2DAction.js +118 -0
  29. package/editor/actions/concrete/ModifyPatchSampler2DAction.spec.js +30 -0
  30. package/editor/actions/concrete/PatchTerrainHeightAction.js +12 -104
  31. package/editor/ecs/component/createObjectEditor.js +53 -29
  32. package/editor/ecs/component/editors/Sampler2DEditor.js +71 -24
  33. package/editor/ecs/component/editors/ecs/terrain/TerrainEditor.js +47 -0
  34. package/editor/ecs/component/editors/primitive/FunctionEditor.js +6 -2
  35. package/editor/tools/SelectionTool.js +1 -1
  36. package/editor/tools/paint/TerrainHeightPaintTool.js +88 -68
  37. package/editor/tools/paint/TerrainPaintTool.js +2 -1
  38. package/editor/tools/paint/TerrainTexturePaintTool.js +8 -73
  39. package/engine/asset/AssetManager.d.ts +1 -1
  40. package/engine/asset/AssetManager.js +390 -388
  41. package/engine/asset/loaders/gltf/extensions/MSFT_texture_dds.js +14 -2
  42. package/engine/ecs/fow/FogOfWarEditor.js +13 -0
  43. package/engine/ecs/terrain/ecs/OffsetScaleTransform2D.d.ts +6 -0
  44. package/engine/ecs/terrain/ecs/Terrain.js +21 -1
  45. package/engine/ecs/terrain/ecs/splat/SplatMapping.js +26 -28
  46. package/engine/ecs/terrain/overlay/TerrainOverlay.js +71 -66
  47. package/engine/ecs/terrain/tiles/TerrainTileManager.js +23 -0
  48. package/engine/ecs/terrain/util/paintTerrainOverlayViaLookupTable.js +13 -7
  49. package/engine/ecs/transform/Transform.d.ts +2 -0
  50. package/engine/ecs/transform/Transform.js +3 -0
  51. package/engine/graphics/ecs/light/Light.js +0 -47
  52. package/engine/graphics/ecs/light/LightSerializationAdapter.js +50 -0
  53. package/engine/graphics/ecs/mesh-v2/DrawMode.js +2 -1
  54. package/engine/graphics/ecs/mesh-v2/build_three_object.js +3 -1
  55. package/engine/graphics/ecs/sprite/Sprite.js +11 -0
  56. package/engine/graphics/ecs/sprite/SpriteSystemPE.js +133 -0
  57. package/engine/graphics/ecs/sprite/prototypeSpriteSystem.js +1566 -0
  58. package/engine/graphics/micron/prototypeVirtualGeometry.js +2 -2
  59. package/engine/graphics/particles/particular/engine/emitter/ParticleLayer.js +17 -9
  60. package/engine/graphics/particles/particular/engine/renderers/ParticleRenderer.js +12 -10
  61. package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +7 -2
  62. package/engine/graphics/particles/particular/engine/renderers/billboard/SoftBillboardParticlePool.js +27 -0
  63. package/engine/graphics/particles/particular/engine/renderers/billboard/SoftBillboardParticleRenderer.js +80 -0
  64. package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +16 -4
  65. package/engine/graphics/shaders/TerrainShader.js +8 -8
  66. package/engine/graphics/texture/atlas/TextureAtlasDebugger.js +2 -1
  67. package/engine/graphics/texture/sampler/Sampler2D.js +190 -201
  68. package/engine/graphics/texture/sampler/Sampler2D.spec.js +34 -35
  69. package/engine/graphics/texture/sampler/bicubic.js +59 -0
  70. package/engine/graphics/texture/sampler/downsampleSample2D.spec.js +2 -2
  71. package/engine/graphics/texture/sampler/genericResampleSampler2D.js +0 -2
  72. package/engine/graphics/texture/sampler/prototypeSamplerFiltering.js +146 -0
  73. package/engine/graphics/texture/sampler/{downsampleSampler2D.js → sampler2D_scale_down_linear.js} +8 -4
  74. package/engine/graphics/texture/sampler/sampler2_d_scale_down_lanczos.js +140 -0
  75. package/engine/graphics/texture/sampler/scaleSampler2D.js +3 -3
  76. package/engine/graphics/texture/sampler/writeSampler2DDataToDataTexture.js +1 -1
  77. package/engine/input/ecs/util/TerrainCameraTargetSampler.js +2 -2
  78. package/engine/navigation/ecs/components/computeNonuniformCatmullRomSplineSample.js +117 -0
  79. package/engine/platform/GetURLHash.js +27 -0
  80. package/engine/platform/WebEnginePlatform.js +1 -22
  81. package/engine/sound/ecs/emitter/SoundEmitter.js +10 -6
  82. package/generation/GridGenerator.js +7 -6
  83. package/generation/example/SampleGenerator0.js +6 -6
  84. package/generation/example/filters/SampleGroundMoistureFilter.js +58 -17
  85. package/generation/example/themes/SampleTheme0.js +11 -7
  86. package/generation/filtering/numeric/CellFilterLiteralFloat.js +5 -0
  87. package/generation/filtering/numeric/complex/CellFilterDilate.js +36 -0
  88. package/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +15 -5
  89. package/generation/filtering/numeric/complex/CellFilterSimplexNoise.js +53 -1
  90. package/generation/filtering/numeric/math/CellFilterMax2.js +3 -0
  91. package/generation/filtering/numeric/math/CellFilterMembershipGeneralizedBell.js +55 -0
  92. package/generation/filtering/numeric/sampling/AbstractCellFilterSampleGridLayer.js +42 -0
  93. package/generation/filtering/numeric/sampling/CellFilterSampleLayerCubic.js +36 -0
  94. package/generation/filtering/numeric/sampling/CellFilterSampleLayerLinear.js +41 -0
  95. package/generation/grid/GridData.d.ts +5 -1
  96. package/generation/grid/GridData.js +35 -36
  97. package/generation/grid/MarkerMatchCounter.js +5 -3
  98. package/generation/markers/GridActionRuleSet.js +15 -32
  99. package/generation/markers/GridCellActionPlaceMarker.js +8 -10
  100. package/generation/markers/debug/visualizeMarkers.js +56 -36
  101. package/generation/markers/emitter/MarkerNodeEmitterFromAction.js +8 -8
  102. package/generation/markers/prototypeGridCellActionPlaceMarker.js +209 -0
  103. package/generation/markers/transform/MarkerNodeTransformerOffsetPosition.js +1 -5
  104. package/generation/markers/transform/MarkerNodeTransformerYRotateByFilterGradient.spec.js +2 -2
  105. package/generation/placement/GridCellPlacementRule.js +10 -3
  106. package/package.json +1 -1
  107. package/samples/terrain/from_image.js +7 -3
  108. package/engine/graphics/particles/particular/engine/renderers/SoftBillboardParticleRenderer.js +0 -7
  109. package/engine/sound/ecs/emitter/attenuate/attenuateSoundLinear.js +0 -11
  110. package/generation/filtering/numeric/CellFilterReadGridLayer.js +0 -73
@@ -123,3 +123,120 @@ export function computeNonuniformCatmullRomSplineSample(result, p0, p1, p2, p3,
123
123
  result[i] = C;
124
124
  }
125
125
  }
126
+
127
+
128
+ /**
129
+ * Alpha assumed to be 0.5
130
+ * @param {number} f
131
+ * @param {number} p0
132
+ * @param {number} p1
133
+ * @param {number} p2
134
+ * @param {number} p3
135
+ * @returns {number}
136
+ */
137
+ function catmullrom_1d(f, p0, p1, p2, p3) {
138
+ const half_alpha = 0.25;
139
+
140
+ /**
141
+ *
142
+ * @param {number} p0
143
+ * @param {number} p1
144
+ * @param {number} half_alpha between 0..0.5
145
+ * @returns {number}
146
+ */
147
+ function getT(p0, p1, half_alpha) {
148
+ const dx = p0 - p1;
149
+
150
+ const a = dx * dx;
151
+
152
+ return Math.pow(a, half_alpha);
153
+ }
154
+
155
+ // calculate T
156
+ const t0 = 0;
157
+ let t_01 = getT(p0, p1, half_alpha);
158
+ let t_02 = getT(p1, p2, half_alpha);
159
+ let t_03 = getT(p2, p3, half_alpha);
160
+
161
+ // safety check for repeated points, to prevent division by 0
162
+ if (t_01 < 1e-5) {
163
+ t_01 = 1;
164
+ }
165
+ if (t_02 < 1e-5) {
166
+ t_02 = t_01;
167
+ }
168
+ if (t_03 < 1e-5) {
169
+ t_03 = t_02;
170
+ }
171
+
172
+ const t1 = t_01 + t0;
173
+ const t2 = t_02 + t1;
174
+ const t3 = t_03 + t2;
175
+
176
+ /**
177
+ * Interpolation between points 1 and 2
178
+ * @type {number}
179
+ */
180
+ const t = t1 * (1 - f) + t2 * f;
181
+
182
+ /*
183
+ Vector2 A1 = (t1-t)/(t1-t0)*p0 + (t-t0)/(t1-t0)*p1;
184
+ Vector2 A2 = (t2-t)/(t2-t1)*p1 + (t-t1)/(t2-t1)*p2;
185
+ Vector2 A3 = (t3-t)/(t3-t2)*p2 + (t-t2)/(t3-t2)*p3;
186
+
187
+ Vector2 B1 = (t2-t)/(t2-t0)*A1 + (t-t0)/(t2-t0)*A2;
188
+ Vector2 B2 = (t3-t)/(t3-t1)*A2 + (t-t1)/(t3-t1)*A3;
189
+
190
+ Vector2 C = (t2-t)/(t2-t1)*B1 + (t-t1)/(t2-t1)*B2;
191
+ */
192
+
193
+ const d_t1_t0 = t1 - t0;
194
+
195
+ const m_A1_0 = (t1 - t) / d_t1_t0;
196
+ const m_A1_1 = (t - t0) / d_t1_t0;
197
+
198
+ const d_t2_t1 = t2 - t1;
199
+
200
+ const m_A2_0 = (t2 - t) / d_t2_t1;
201
+
202
+ const d_t_t1 = t - t1;
203
+
204
+ const m_A2_1 = d_t_t1 / d_t2_t1;
205
+
206
+ const d_t3_t2 = t3 - t2;
207
+
208
+ const d_t3_t = t3 - t;
209
+
210
+ const m_A3_0 = d_t3_t / d_t3_t2;
211
+ const m_A3_1 = (t - t2) / d_t3_t2;
212
+
213
+ const d_t2_t0 = t2 - t0;
214
+
215
+ const m_B1_0 = (t2 - t) / d_t2_t0;
216
+ const m_B1_1 = (t - t0) / d_t2_t0;
217
+
218
+ const d_t3_t1 = t3 - t1;
219
+
220
+ const m_B2_0 = d_t3_t / d_t3_t1;
221
+ const m_B2_1 = d_t_t1 / d_t3_t1;
222
+
223
+ const m_C_0 = (t2 - t) / d_t2_t1;
224
+ const m_C_1 = d_t_t1 / d_t2_t1;
225
+
226
+ // read vector values for the dimension
227
+ const v0 = p0;
228
+ const v1 = p1;
229
+ const v2 = p2;
230
+ const v3 = p3;
231
+
232
+ // compute resulting value in this dimension
233
+ const A1 = m_A1_0 * v0 + m_A1_1 * v1;
234
+ const A2 = m_A2_0 * v1 + m_A2_1 * v2;
235
+ const A3 = m_A3_0 * v2 + m_A3_1 * v3;
236
+
237
+ const B1 = m_B1_0 * A1 + m_B1_1 * A2;
238
+ const B2 = m_B2_0 * A2 + m_B2_1 * A3;
239
+
240
+ return m_C_0 * B1 + m_C_1 * B2;
241
+
242
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * extracts hash parameters
3
+ * @returns {Object<string>}
4
+ */
5
+ export function getURLHash() {
6
+ const result = {};
7
+
8
+ if (window === undefined) {
9
+ return result;
10
+ }
11
+
12
+ const location = window.location;
13
+
14
+ const hash = location.hash;
15
+
16
+ const hashRegEx = /([a-zA-Z0-9\-\_]+)\=([a-zA-Z0-9\-\_]+)/g;
17
+
18
+ let match;
19
+ while ((match = hashRegEx.exec(hash)) !== null) {
20
+ const variableName = match[1];
21
+ const value = match[2];
22
+
23
+ result[variableName] = value;
24
+ }
25
+
26
+ return result;
27
+ }
@@ -2,6 +2,7 @@ import { EnginePlatform } from "./EnginePlatform.js";
2
2
  import { IndexedDBStorage } from "../save/storage/IndexedDBStorage.js";
3
3
  import { StorageAchievementGateway } from "../achievements/gateway/StorageAchievementGateway.js";
4
4
  import { arrayPickBestElement } from "../../core/collection/array/arrayPickBestElement.js";
5
+ import { getURLHash } from "./GetURLHash.js";
5
6
 
6
7
  export class WebEnginePlatform extends EnginePlatform {
7
8
  constructor({
@@ -32,29 +33,7 @@ export class WebEnginePlatform extends EnginePlatform {
32
33
  }
33
34
 
34
35
  pickDefaultLocale(localeOptions) {
35
- function getURLHash() {
36
- const result = {};
37
36
 
38
- if (window === undefined) {
39
- return result;
40
- }
41
-
42
- const location = window.location;
43
-
44
- const hash = location.hash;
45
-
46
- const hashRegEx = /([a-zA-Z0-9\-\_]+)\=([a-zA-Z0-9\-\_]+)/g;
47
-
48
- let match;
49
- while ((match = hashRegEx.exec(hash)) !== null) {
50
- const variableName = match[1];
51
- const value = match[2];
52
-
53
- result[variableName] = value;
54
- }
55
-
56
- return result;
57
- }
58
37
 
59
38
  function pickLanguageByNavigator() {
60
39
  /**
@@ -8,10 +8,14 @@ import Vector1 from "../../../../core/geom/Vector1.js";
8
8
  import { SoundTrack } from "./SoundTrack.js";
9
9
  import { SoundEmitterFlags } from "./SoundEmitterFlags.js";
10
10
  import { SoundAttenuationFunction } from "./SoundAttenuationFunction.js";
11
- import { attenuateSoundLinear } from "./attenuate/attenuateSoundLinear.js";
12
- import { attenuateSoundLogarithmic } from "./attenuate/attenuateSoundLogarithmic.js";
11
+ import {
12
+ interpolate_irradiance_linear
13
+ } from "../../../../core/math/physics/irradiance/interpolate_irradiance_linear.js";
14
+ import {
15
+ interpolate_irradiance_lograrithmic
16
+ } from "../../../../core/math/physics/irradiance/interpolate_irradiance_lograrithmic.js";
13
17
  import { SoundPanningModelType } from "./SoundPanningModelType.js";
14
- import { attenuateSoundSmith } from "./attenuate/attenuateSoundSmith.js";
18
+ import { interpolate_irradiance_smith } from "../../../../core/math/physics/irradiance/interpolate_irradiance_smith.js";
15
19
  import { objectKeyByValue } from "../../../../core/model/object/objectKeyByValue.js";
16
20
  import { computeStringHash } from "../../../../core/primitives/strings/computeStringHash.js";
17
21
  import { computeHashIntegerArray } from "../../../../core/collection/array/computeHashIntegerArray.js";
@@ -354,11 +358,11 @@ export class SoundEmitter {
354
358
  const distance_max = this.__distanceMax;
355
359
 
356
360
  if (attenuation === SoundAttenuationFunction.Linear) {
357
- volume = attenuateSoundLinear(distance, distance_min, distance_max);
361
+ volume = interpolate_irradiance_linear(distance, distance_min, distance_max);
358
362
  } else if (attenuation === SoundAttenuationFunction.Logarithmic) {
359
- volume = attenuateSoundLogarithmic(distance, distance_min, distance_max);
363
+ volume = interpolate_irradiance_lograrithmic(distance, distance_min, distance_max);
360
364
  } else if (attenuation === SoundAttenuationFunction.Smith) {
361
- volume = attenuateSoundSmith(distance, distance_min, distance_max);
365
+ volume = interpolate_irradiance_smith(distance, distance_min, distance_max);
362
366
  } else {
363
367
  //unsupported function, don't attenuate
364
368
  volume = 1;
@@ -34,11 +34,12 @@ export class GridGenerator {
34
34
  */
35
35
  const tasks = [];
36
36
 
37
- const n = this.generators.length;
37
+ const generators = this.generators;
38
+ const generator_count = generators.length;
38
39
 
39
40
  //generate tasks
40
- for (let i = 0; i < n; i++) {
41
- const generator = this.generators[i];
41
+ for (let i = 0; i < generator_count; i++) {
42
+ const generator = generators[i];
42
43
 
43
44
  const task = generator.build(grid, ecd, seed);
44
45
 
@@ -46,8 +47,8 @@ export class GridGenerator {
46
47
  }
47
48
 
48
49
  //assign dependencies
49
- for (let i = 0; i < n; i++) {
50
- const generator = this.generators[i];
50
+ for (let i = 0; i < generator_count; i++) {
51
+ const generator = generators[i];
51
52
 
52
53
  const task = tasks[i];
53
54
 
@@ -59,7 +60,7 @@ export class GridGenerator {
59
60
 
60
61
  const dependency = dependencies[j];
61
62
 
62
- const dependencyIndex = this.generators.indexOf(dependency);
63
+ const dependencyIndex = generators.indexOf(dependency);
63
64
 
64
65
  if (dependencyIndex === -1) {
65
66
  throw new Error(`Dependency ${j}(name='${dependency.name}') of task generator [${i}] (name='${generator.name}') is not found`);
@@ -34,7 +34,7 @@ import { CellMatcherAny } from "../rules/CellMatcherAny.js";
34
34
  import { CellFilterGaussianBlur } from "../filtering/numeric/complex/CellFilterGaussianBlur.js";
35
35
  import { GridCellActionSequence } from "../placement/action/util/GridCellActionSequence.js";
36
36
  import { CellFilterStep } from "../filtering/numeric/math/CellFilterStep.js";
37
- import { CellFilterReadGridLayer } from "../filtering/numeric/CellFilterReadGridLayer.js";
37
+ import { CellFilterSampleLayerLinear } from "../filtering/numeric/sampling/CellFilterSampleLayerLinear.js";
38
38
  import { CellFilterAngleToNormal } from "../filtering/numeric/complex/CellFilterAngleToNormal.js";
39
39
  import Vector3 from "../../core/geom/Vector3.js";
40
40
  import { CellFilterOneMinus } from "../filtering/numeric/math/CellFilterOneMinus.js";
@@ -138,7 +138,7 @@ const ACTION_PLACE_ENEMY_MARKER = GridCellActionPlaceMarker.from({
138
138
  CellFilterSubtract.from(
139
139
  CellFilterMultiply.from(
140
140
  CellFilterDivide.from(
141
- CellFilterReadGridLayer.from(MirGridLayers.DistanceFromStart),
141
+ CellFilterSampleLayerLinear.from(MirGridLayers.DistanceFromStart),
142
142
  //increase level by 1 for each X tiles distance
143
143
  CellFilterLiteralFloat.from(20)
144
144
  ),
@@ -147,7 +147,7 @@ const ACTION_PLACE_ENEMY_MARKER = GridCellActionPlaceMarker.from({
147
147
  CellFilterSmoothStep.from(
148
148
  CellFilterLiteralFloat.from(20),
149
149
  CellFilterLiteralFloat.from(50),
150
- CellFilterReadGridLayer.from(MirGridLayers.DistanceFromStart)
150
+ CellFilterSampleLayerLinear.from(MirGridLayers.DistanceFromStart)
151
151
  ),
152
152
  CellFilterLerp.from(
153
153
  CellFilterLiteralFloat.from(0.9),
@@ -277,7 +277,7 @@ const gDrawLayerMoisture = GridTaskActionRuleSet.from({
277
277
  });
278
278
 
279
279
  //trees
280
- const fReadHeight = CellFilterReadGridLayer.from(MirGridLayers.Heights);
280
+ const fReadHeight = CellFilterSampleLayerLinear.from(MirGridLayers.Heights);
281
281
 
282
282
  const fTreeArea = CellFilterCache.from(
283
283
  CellFilterMultiply.from(
@@ -287,7 +287,7 @@ const fTreeArea = CellFilterCache.from(
287
287
  CellFilterInverseLerp.from(
288
288
  CellFilterLiteralFloat.from(0.1),
289
289
  CellFilterLiteralFloat.from(0.5),
290
- CellFilterReadGridLayer.from(MirGridLayers.Moisture)
290
+ CellFilterSampleLayerLinear.from(MirGridLayers.Moisture)
291
291
  ),
292
292
  CellFilterLiteralFloat.from(0),
293
293
  CellFilterLiteralFloat.from(1)
@@ -408,7 +408,7 @@ const fSharpSlope = CellFilterCache.from(
408
408
  CellFilterLiteralFloat.from(Math.PI / 5),
409
409
  CellFilterLiteralFloat.from(Math.PI / 3.5),
410
410
  CellFilterAngleToNormal.from(
411
- CellFilterReadGridLayer.from(MirGridLayers.Heights),
411
+ CellFilterSampleLayerLinear.from(MirGridLayers.Heights),
412
412
  Vector3.forward
413
413
  )
414
414
  )
@@ -1,32 +1,73 @@
1
- import { CellFilterAdd } from "../../filtering/numeric/math/algebra/CellFilterAdd.js";
2
1
  import { CellFilterMultiply } from "../../filtering/numeric/math/algebra/CellFilterMultiply.js";
3
2
  import { CellFilterSimplexNoise } from "../../filtering/numeric/complex/CellFilterSimplexNoise.js";
4
3
  import { CellFilterLiteralFloat } from "../../filtering/numeric/CellFilterLiteralFloat.js";
5
4
  import { CellFilterGaussianBlur } from "../../filtering/numeric/complex/CellFilterGaussianBlur.js";
6
- import { CellFilterOneMinus } from "../../filtering/numeric/math/CellFilterOneMinus.js";
7
5
  import { CellFilterStep } from "../../filtering/numeric/math/CellFilterStep.js";
8
- import { CellFilterReadGridLayer } from "../../filtering/numeric/CellFilterReadGridLayer.js";
6
+ import { CellFilterSampleLayerLinear } from "../../filtering/numeric/sampling/CellFilterSampleLayerLinear.js";
9
7
  import { MirGridLayers } from "../grid/MirGridLayers.js";
8
+ import { CellFilterMax2 } from "../../filtering/numeric/math/CellFilterMax2.js";
9
+ import { CellFilterSmoothStep } from "../../filtering/numeric/math/CellFilterSmoothStep.js";
10
+ import { MohGridLayers } from "../../../../../generator/MohGridLayers.js";
11
+ import { CellFilterDilate } from "../../filtering/numeric/complex/CellFilterDilate.js";
12
+ import { DEG2RAD } from "three/src/math/MathUtils.js";
13
+ import { CellFilterCache } from "../../filtering/numeric/CellFilterCache.js";
10
14
 
11
- const fReadHeight = CellFilterReadGridLayer.from(MirGridLayers.Heights);
15
+ const fReadHeight = CellFilterSampleLayerLinear.from(MirGridLayers.Heights);
12
16
 
13
- export const SampleGroundMoistureFilter = CellFilterAdd.from(
17
+ const WATER_MASK = CellFilterStep.from(fReadHeight, CellFilterLiteralFloat.from(-0.05));
18
+ const CURVATURE = CellFilterSampleLayerLinear.from(MohGridLayers.Curvature);
19
+ const SLOPE = CellFilterSampleLayerLinear.from(MohGridLayers.Slope);
20
+
21
+
22
+ export const SampleGroundMoistureFilter = CellFilterMax2.from(
14
23
  // add regional variation in relative moisture
15
24
  CellFilterMultiply.from(
16
- CellFilterSimplexNoise.from(100, 100),
17
- CellFilterLiteralFloat.from(0.4)
25
+ CellFilterMultiply.from(
26
+ CellFilterSimplexNoise.fractal(2, 100, 1263),
27
+ CellFilterMax2.from(
28
+ // flat areas are more likely to be keep moisture
29
+ CellFilterSmoothStep.from(
30
+ CellFilterLiteralFloat.from(40 * DEG2RAD),
31
+ CellFilterLiteralFloat.from(10 * DEG2RAD),
32
+ SLOPE
33
+ ),
34
+ // water accumulates in crevices
35
+ CellFilterSmoothStep.from(
36
+ CellFilterLiteralFloat.from(0.0),
37
+ CellFilterLiteralFloat.from(0.1),
38
+ CURVATURE
39
+ )
40
+ )
41
+ ),
42
+
43
+ CellFilterLiteralFloat.from(0.5)
18
44
  ),
19
45
 
20
- //simulate water distribution from lakes/rivers/sees into the nearby ground
21
- CellFilterMultiply.from(
22
- CellFilterGaussianBlur.from(
23
- CellFilterOneMinus.from(
24
- CellFilterStep.from(CellFilterLiteralFloat.from(0), fReadHeight)
25
- ),
26
- 7,
27
- 7,
28
- 1
46
+ //simulate water diffusion from lakes/rivers/sees into the nearby ground
47
+ CellFilterGaussianBlur.from(
48
+ CellFilterCache.from(
49
+ CellFilterMax2.from(
50
+ WATER_MASK,
51
+ CellFilterMultiply.from(
52
+ CellFilterGaussianBlur.from(
53
+ CellFilterCache.from(CellFilterDilate.from(WATER_MASK)),
54
+ 5,
55
+ 5,
56
+ 1
57
+ ),
58
+ /*
59
+ Diffuse more along surfaces with low slope (flat)
60
+ NOTE: we don't have to worry about directly of the slope, as water always starts at 0, so any slope will be positive in effect
61
+ */
62
+ CellFilterSmoothStep.from(
63
+ CellFilterLiteralFloat.from(35 * DEG2RAD),
64
+ CellFilterLiteralFloat.from(10 * DEG2RAD),
65
+ SLOPE
66
+ ),
67
+ )
68
+ )
29
69
  ),
30
- CellFilterLiteralFloat.from(0.6)
70
+ 3, 3, 1
31
71
  )
32
72
  );
73
+
@@ -21,13 +21,17 @@ import Tag from "../../../engine/ecs/components/Tag.js";
21
21
  import HeadsUpDisplay from "../../../engine/ecs/gui/hud/HeadsUpDisplay.js";
22
22
  import ViewportPosition from "../../../engine/ecs/gui/position/ViewportPosition.js";
23
23
  import GUIElement from "../../../engine/ecs/gui/GUIElement.js";
24
- import { MarkerNodeTransformerYRotateByFilterGradient } from "../../markers/transform/MarkerNodeTransformerYRotateByFilterGradient.js";
24
+ import {
25
+ MarkerNodeTransformerYRotateByFilterGradient
26
+ } from "../../markers/transform/MarkerNodeTransformerYRotateByFilterGradient.js";
25
27
  import { PI_HALF } from "../../../core/math/MathUtils.js";
26
28
  import { CellFilterGaussianBlur } from "../../filtering/numeric/complex/CellFilterGaussianBlur.js";
27
29
  import { CellProcessingRule } from "../../theme/cell/CellProcessingRule.js";
28
- import { ContinuousGridCellActionSetTerrainHeight } from "../../grid/actions/ContinuousGridCellActionSetTerrainHeight.js";
30
+ import {
31
+ ContinuousGridCellActionSetTerrainHeight
32
+ } from "../../grid/actions/ContinuousGridCellActionSetTerrainHeight.js";
29
33
  import { MirGridLayers } from "../grid/MirGridLayers.js";
30
- import { CellFilterReadGridLayer } from "../../filtering/numeric/CellFilterReadGridLayer.js";
34
+ import { CellFilterSampleLayerLinear } from "../../filtering/numeric/sampling/CellFilterSampleLayerLinear.js";
31
35
  import ClingToTerrain from "../../../engine/ecs/terrain/ecs/ClingToTerrain.js";
32
36
  import { MarkerNodeTransformerYRotateByFilter } from "../../markers/transform/MarkerNodeTransformerYRotateByFilter.js";
33
37
  import { CellFilterAngleToNormal } from "../../filtering/numeric/complex/CellFilterAngleToNormal.js";
@@ -55,14 +59,14 @@ const terrainTheme = new TerrainTheme();
55
59
 
56
60
  const matcher_tag_road = CellMatcherLayerBitMaskTest.from(GridTags.Road, MirGridLayers.Tags);
57
61
 
58
- const filterMoisture = CellFilterReadGridLayer.from(MirGridLayers.Moisture);
62
+ const filterMoisture = CellFilterSampleLayerLinear.from(MirGridLayers.Moisture);
59
63
 
60
64
  const filterRock = CellFilterClamp.from(
61
65
  CellFilterSmoothStep.from(
62
66
  CellFilterLiteralFloat.from(Math.PI / 5),
63
67
  CellFilterLiteralFloat.from(Math.PI / 3.5),
64
68
  CellFilterAngleToNormal.from(
65
- CellFilterReadGridLayer.from(MirGridLayers.Heights),
69
+ CellFilterSampleLayerLinear.from(MirGridLayers.Heights),
66
70
  Vector3.forward
67
71
  )
68
72
  ),
@@ -101,7 +105,7 @@ const filterSand = CellFilterMultiply.from(
101
105
  CellFilterLiteralFloat.from(0),
102
106
  CellFilterLiteralFloat.from(0.2),
103
107
  CellFilterNegate.from(
104
- CellFilterReadGridLayer.from(MirGridLayers.Heights)
108
+ CellFilterSampleLayerLinear.from(MirGridLayers.Heights)
105
109
  )
106
110
  ),
107
111
  3,
@@ -1562,7 +1566,7 @@ SampleTheme0.nodes.add(MarkerProcessingRule.from({
1562
1566
 
1563
1567
  const aHeight = new ContinuousGridCellActionSetTerrainHeight();
1564
1568
 
1565
- aHeight.target = CellFilterReadGridLayer.from(MirGridLayers.Heights);
1569
+ aHeight.target = CellFilterSampleLayerLinear.from(MirGridLayers.Heights);
1566
1570
 
1567
1571
  SampleTheme0.cells.add(CellProcessingRule.from(
1568
1572
  CellFilterLiteralFloat.from(1),
@@ -37,3 +37,8 @@ export class CellFilterLiteralFloat extends CellFilter {
37
37
  * @type {CellFilterLiteralFloat}
38
38
  */
39
39
  CellFilterLiteralFloat.ONE = CellFilterLiteralFloat.from(1);
40
+ /**
41
+ * @readonly
42
+ * @type {CellFilterLiteralFloat}
43
+ */
44
+ CellFilterLiteralFloat.ZERO = CellFilterLiteralFloat.from(0);
@@ -0,0 +1,36 @@
1
+ import { CellFilter } from "../../CellFilter.js";
2
+ import { max2 } from "../../../../core/math/max2.js";
3
+ import { CellFilterUnaryOperation } from "../../core/CellFilterUnaryOperation.js";
4
+ import { assert } from "../../../../core/assert.js";
5
+
6
+ export class CellFilterDilate extends CellFilterUnaryOperation {
7
+ /**
8
+ *
9
+ * @param {CellFilter} source
10
+ * @returns {CellFilterDilate}
11
+ */
12
+ static from(source) {
13
+ const r = new CellFilterDilate();
14
+ assert.equal(source.isCellFilter, true, 'source.isCellFilter !== true');
15
+
16
+ r.source = source;
17
+
18
+ return r;
19
+ }
20
+
21
+ execute(grid, x, y, rotation) {
22
+ const filter = this.source;
23
+
24
+ let result = Number.NEGATIVE_INFINITY;
25
+
26
+ for (let _y = -1; _y <= 1; _y++) {
27
+ for (let _x = -1; _x <= 1; _x++) {
28
+ const v = filter.execute(grid, x + _x, y + _y, 0);
29
+
30
+ result = max2(result, v);
31
+ }
32
+ }
33
+
34
+ return result;
35
+ }
36
+ }
@@ -81,14 +81,20 @@ export class CellFilterGaussianBlur extends CellFilter {
81
81
  }
82
82
 
83
83
  initialize(grid, seed) {
84
+ if (this.initialized) {
85
+ return;
86
+ }
87
+
84
88
  if (!this.source.initialized) {
85
89
  this.source.initialize(grid, seed);
90
+ }
86
91
 
87
- this.__kernel = new Float32Array(this.samples_x * this.samples_y);
92
+ this.__kernel = new Float32Array(this.samples_x * this.samples_y);
88
93
 
89
- // initialize kernel
90
- this.__kernel_total_power = buildKernel(this.__kernel, this.samples_x, this.samples_y, this.sigma_x, this.sigma_y);
91
- }
94
+ // initialize kernel
95
+ this.__kernel_total_power = buildKernel(this.__kernel, this.samples_x, this.samples_y, this.sigma_x, this.sigma_y);
96
+
97
+ super.initialize(grid, seed);
92
98
  }
93
99
 
94
100
 
@@ -115,6 +121,8 @@ export class CellFilterGaussianBlur extends CellFilter {
115
121
  }
116
122
 
117
123
  execute(grid, x, y, rotation) {
124
+ assert.ok(this.__initialized, 'not initialized');
125
+
118
126
  const samplesX = this.samples_x;
119
127
  const samplesY = this.samples_y;
120
128
 
@@ -156,7 +164,9 @@ export class CellFilterGaussianBlur extends CellFilter {
156
164
 
157
165
  const sourceValue = source.execute(grid, x + offset_x, y + offset_y, 0);
158
166
 
159
- sum += sourceValue * power;
167
+ const sample_contribution = sourceValue * power;
168
+
169
+ sum += sample_contribution;
160
170
 
161
171
  }
162
172
  }
@@ -1,6 +1,10 @@
1
1
  import { seededRandom } from "../../../../core/math/random/seededRandom.js";
2
2
  import { CellFilter } from "../../CellFilter.js";
3
3
  import SimplexNoise from "simplex-noise";
4
+ import { CellFilterAdd } from "../math/algebra/CellFilterAdd.js";
5
+ import { CellFilterMultiply } from "../math/algebra/CellFilterMultiply.js";
6
+ import { CellFilterLiteralFloat } from "../CellFilterLiteralFloat.js";
7
+ import { CellFilterDivide } from "../math/algebra/CellFilterDivide.js";
4
8
 
5
9
  export class CellFilterSimplexNoise extends CellFilter {
6
10
  constructor() {
@@ -14,7 +18,7 @@ export class CellFilterSimplexNoise extends CellFilter {
14
18
 
15
19
  /**
16
20
  * @private
17
- * @type {Function}
21
+ * @type {function}
18
22
  */
19
23
  this.random = seededRandom(0);
20
24
 
@@ -29,6 +33,54 @@ export class CellFilterSimplexNoise extends CellFilter {
29
33
  this.__seed = 0;
30
34
  }
31
35
 
36
+ /**
37
+ * Build a fractal noise filter with a given number of octaves
38
+ * @param {number} octaves
39
+ * @param {number} scale
40
+ * @param {number} persistence
41
+ * @param {number} lacunarity
42
+ * @param {number} seed
43
+ * @returns {CellFilter}
44
+ */
45
+ static fractal(octaves, scale, seed = 0, persistence = 0.5, lacunarity = 2) {
46
+ let s = seed;
47
+ let r;
48
+
49
+ let frequency = 1;
50
+ let amplitude = 1;
51
+ let totalAmplitude = 0;
52
+
53
+ for (let i = 0; i < octaves; i++) {
54
+ const noise = CellFilterSimplexNoise.from(scale * frequency, scale * frequency, s);
55
+
56
+ if (r === undefined) {
57
+ r = noise;
58
+ } else {
59
+ r = CellFilterAdd.from(
60
+ CellFilterMultiply.from(noise, CellFilterLiteralFloat.from(amplitude)),
61
+ r
62
+ );
63
+ }
64
+
65
+ totalAmplitude += amplitude;
66
+ amplitude *= persistence;
67
+ frequency *= lacunarity;
68
+
69
+ s = (s + 1) * 31;
70
+ }
71
+
72
+ if (totalAmplitude === 1) {
73
+ return r;
74
+ } else {
75
+
76
+ return CellFilterDivide.from(
77
+ r,
78
+ CellFilterLiteralFloat.from(totalAmplitude)
79
+ );
80
+
81
+ }
82
+ }
83
+
32
84
  /**
33
85
  *
34
86
  * @param {number} scale_x
@@ -24,6 +24,9 @@ export class CellFilterMax2 extends CellFilterBinaryOperation {
24
24
  }
25
25
 
26
26
  operation(left, right) {
27
+ assert.notNaN(left,'left');
28
+ assert.notNaN(right,'right');
29
+
27
30
  return max2(left, right);
28
31
  }
29
32
  }