@woosh/meep-engine 2.86.1 → 2.86.3
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.
- package/build/bundle-worker-terrain.js +1 -1
- package/build/meep.cjs +19 -2
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +19 -2
- package/package.json +1 -1
- package/src/core/math/makeNextOdd.d.ts +8 -0
- package/src/core/math/makeNextOdd.d.ts.map +1 -0
- package/src/core/math/makeNextOdd.js +15 -0
- package/src/engine/ecs/terrain/util/paintTerrainOverlayViaLookupTable.d.ts +16 -7
- package/src/engine/ecs/terrain/util/paintTerrainOverlayViaLookupTable.d.ts.map +1 -1
- package/src/engine/ecs/terrain/util/paintTerrainOverlayViaLookupTable.js +8 -7
- package/src/engine/graphics/texture/sampler/Sampler2D.d.ts.map +1 -1
- package/src/engine/graphics/texture/sampler/Sampler2D.js +19 -2
- package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.d.ts +9 -0
- package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.d.ts.map +1 -0
- package/src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.js +93 -0
- package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.d.ts.map +1 -1
- package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +3 -18
package/build/meep.module.js
CHANGED
|
@@ -49553,9 +49553,26 @@ class Sampler2D {
|
|
|
49553
49553
|
const i0 = (y * width + x) * itemSize;
|
|
49554
49554
|
|
|
49555
49555
|
for (let i = 0; i < itemSize; i++) {
|
|
49556
|
-
|
|
49556
|
+
result[i] = this.data[i0 + i];
|
|
49557
|
+
}
|
|
49558
|
+
}
|
|
49559
|
+
|
|
49560
|
+
/**
|
|
49561
|
+
*
|
|
49562
|
+
* @param {number} x
|
|
49563
|
+
* @param {number} y
|
|
49564
|
+
* @param {number[]|ArrayLike<number>} data
|
|
49565
|
+
*/
|
|
49566
|
+
write(x, y, data) {
|
|
49557
49567
|
|
|
49558
|
-
|
|
49568
|
+
const width = this.width;
|
|
49569
|
+
|
|
49570
|
+
const itemSize = this.itemSize;
|
|
49571
|
+
|
|
49572
|
+
const i0 = (y * width + x) * itemSize;
|
|
49573
|
+
|
|
49574
|
+
for (let i = 0; i < itemSize; i++) {
|
|
49575
|
+
this.data[i0 + i] = result[i];
|
|
49559
49576
|
}
|
|
49560
49577
|
}
|
|
49561
49578
|
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"makeNextOdd.d.ts","sourceRoot":"","sources":["../../../../src/core/math/makeNextOdd.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,+BAHW,MAAM,GACL,MAAM,CAUjB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* even number of samples, make odd to ensure we sample reference point
|
|
4
|
+
* @param {number} x
|
|
5
|
+
* @return {number}
|
|
6
|
+
*/
|
|
7
|
+
export function makeNextOdd(x) {
|
|
8
|
+
if (x % 2 === 0) {
|
|
9
|
+
// even, make odd
|
|
10
|
+
return x + 1;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// already odd
|
|
14
|
+
return x;
|
|
15
|
+
}
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @param {TerrainOverlay} overlay
|
|
4
|
-
* @param {Sampler2D} sampler
|
|
5
|
-
* @param {ParameterLookupTable} [lut]
|
|
6
|
-
* @param {NumericInterval} range Range of values of interest within the sampler that are to be mapped onto LUT
|
|
7
|
-
* @param {function(number):number} [lookupScaleFunction]
|
|
2
|
+
* @param {Object} params
|
|
3
|
+
* @param {TerrainOverlay} params.overlay
|
|
4
|
+
* @param {Sampler2D} params.sampler
|
|
5
|
+
* @param {ParameterLookupTable} [params.lut]
|
|
6
|
+
* @param {NumericInterval} [params.range] Range of values of interest within the sampler that are to be mapped onto LUT
|
|
7
|
+
* @param {function(number):number} [params.lookupScaleFunction]
|
|
8
8
|
*/
|
|
9
|
-
export function paintTerrainOverlayViaLookupTable({ overlay, sampler, lut, range, lookupScaleFunction }:
|
|
9
|
+
export function paintTerrainOverlayViaLookupTable({ overlay, sampler, lut, range, lookupScaleFunction }: {
|
|
10
|
+
overlay: TerrainOverlay;
|
|
11
|
+
sampler: Sampler2D;
|
|
12
|
+
lut?: ParameterLookupTable;
|
|
13
|
+
range?: NumericInterval;
|
|
14
|
+
lookupScaleFunction?: (arg0: number) => number;
|
|
15
|
+
}): void;
|
|
16
|
+
import { Sampler2D } from "../../../graphics/texture/sampler/Sampler2D.js";
|
|
17
|
+
import { ParameterLookupTable } from "../../../graphics/particles/particular/engine/parameter/ParameterLookupTable.js";
|
|
18
|
+
import { NumericInterval } from "../../../../core/math/interval/NumericInterval.js";
|
|
10
19
|
//# sourceMappingURL=paintTerrainOverlayViaLookupTable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paintTerrainOverlayViaLookupTable.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/terrain/util/paintTerrainOverlayViaLookupTable.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"paintTerrainOverlayViaLookupTable.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/terrain/util/paintTerrainOverlayViaLookupTable.js"],"names":[],"mappings":"AAmBA;;;;;;;GAOG;AACH;IANkC,OAAO;IACZ,OAAO,EAAzB,SAAS;IACqB,GAAG,GAAjC,oBAAoB;IACK,KAAK,GAA9B,eAAe;IACkB,mBAAmB,UAA3C,MAAM,KAAE,MAAM;SA0CjC;0BA9DyB,gDAAgD;qCAFrC,iFAAiF;gCADtF,mDAAmD"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { passThrough } from "../../../../core/function/passThrough.js";
|
|
2
2
|
import { clamp01 } from "../../../../core/math/clamp01.js";
|
|
3
|
+
import { NumericInterval } from "../../../../core/math/interval/NumericInterval.js";
|
|
3
4
|
import { ParameterLookupTable } from "../../../graphics/particles/particular/engine/parameter/ParameterLookupTable.js";
|
|
4
5
|
import { sampler2d_scale } from "../../../graphics/texture/sampler/resize/sampler2d_scale.js";
|
|
5
6
|
import { Sampler2D } from "../../../graphics/texture/sampler/Sampler2D.js";
|
|
@@ -17,18 +18,18 @@ heatmap_lut.write([
|
|
|
17
18
|
heatmap_lut.computeUniformPositions();
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
|
-
*
|
|
21
|
-
* @param {TerrainOverlay} overlay
|
|
22
|
-
* @param {Sampler2D} sampler
|
|
23
|
-
* @param {ParameterLookupTable} [lut]
|
|
24
|
-
* @param {NumericInterval} range Range of values of interest within the sampler that are to be mapped onto LUT
|
|
25
|
-
* @param {function(number):number} [lookupScaleFunction]
|
|
21
|
+
* @param {Object} params
|
|
22
|
+
* @param {TerrainOverlay} params.overlay
|
|
23
|
+
* @param {Sampler2D} params.sampler
|
|
24
|
+
* @param {ParameterLookupTable} [params.lut]
|
|
25
|
+
* @param {NumericInterval} [params.range] Range of values of interest within the sampler that are to be mapped onto LUT
|
|
26
|
+
* @param {function(number):number} [params.lookupScaleFunction]
|
|
26
27
|
*/
|
|
27
28
|
export function paintTerrainOverlayViaLookupTable({
|
|
28
29
|
overlay,
|
|
29
30
|
sampler,
|
|
30
31
|
lut = heatmap_lut,
|
|
31
|
-
range,
|
|
32
|
+
range = new NumericInterval(0, 1),
|
|
32
33
|
lookupScaleFunction = passThrough
|
|
33
34
|
}) {
|
|
34
35
|
let i, j;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sampler2D.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/texture/sampler/Sampler2D.js"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH;
|
|
1
|
+
{"version":3,"file":"Sampler2D.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/texture/sampler/Sampler2D.js"],"names":[],"mappings":"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"}
|
|
@@ -491,9 +491,26 @@ export class Sampler2D {
|
|
|
491
491
|
const i0 = (y * width + x) * itemSize;
|
|
492
492
|
|
|
493
493
|
for (let i = 0; i < itemSize; i++) {
|
|
494
|
-
|
|
494
|
+
result[i] = this.data[i0 + i];
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
*
|
|
500
|
+
* @param {number} x
|
|
501
|
+
* @param {number} y
|
|
502
|
+
* @param {number[]|ArrayLike<number>} data
|
|
503
|
+
*/
|
|
504
|
+
write(x, y, data) {
|
|
495
505
|
|
|
496
|
-
|
|
506
|
+
const width = this.width;
|
|
507
|
+
|
|
508
|
+
const itemSize = this.itemSize;
|
|
509
|
+
|
|
510
|
+
const i0 = (y * width + x) * itemSize;
|
|
511
|
+
|
|
512
|
+
for (let i = 0; i < itemSize; i++) {
|
|
513
|
+
this.data[i0 + i] = data[i];
|
|
497
514
|
}
|
|
498
515
|
}
|
|
499
516
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {Sampler2D} output
|
|
4
|
+
* @param {Sampler2D} input
|
|
5
|
+
* @param {number} size
|
|
6
|
+
* @param {number} [quality]
|
|
7
|
+
*/
|
|
8
|
+
export function sampler2d_blur_gaussian(output: Sampler2D, input: Sampler2D, size: number, quality?: number): void;
|
|
9
|
+
//# sourceMappingURL=sampler2d_blur_gaussian.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sampler2d_blur_gaussian.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/graphics/texture/sampler/filter/sampler2d_blur_gaussian.js"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,mFAHW,MAAM,YACN,MAAM,QAmFhB"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { gaussian } from "../../../../../core/math/gaussian.js";
|
|
2
|
+
import { makeNextOdd } from "../../../../../core/math/makeNextOdd.js";
|
|
3
|
+
import { max2 } from "../../../../../core/math/max2.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {Sampler2D} output
|
|
8
|
+
* @param {Sampler2D} input
|
|
9
|
+
* @param {number} size
|
|
10
|
+
* @param {number} [quality]
|
|
11
|
+
*/
|
|
12
|
+
export function sampler2d_blur_gaussian(output, input, size, quality = 1) {
|
|
13
|
+
|
|
14
|
+
const sample_count = max2(3, makeNextOdd(Math.round(size * quality)));
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
const kernel = new Float32Array(sample_count);
|
|
18
|
+
|
|
19
|
+
const sigma = 10;
|
|
20
|
+
|
|
21
|
+
for (let i = 0; i < sample_count; i++) {
|
|
22
|
+
const local = i - sample_count * 0.5;
|
|
23
|
+
|
|
24
|
+
kernel[i] = gaussian(sigma, local);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const width = input.width;
|
|
28
|
+
const height = input.height;
|
|
29
|
+
|
|
30
|
+
let source = input;
|
|
31
|
+
let target = output;
|
|
32
|
+
|
|
33
|
+
const half_samples = (sample_count - 1) * 0.5;
|
|
34
|
+
const local_u_scale = width / (sample_count - 1);
|
|
35
|
+
const local_v_scale = height / (sample_count - 1);
|
|
36
|
+
|
|
37
|
+
const channel_count = input.itemSize;
|
|
38
|
+
const sample = new Float64Array(channel_count);
|
|
39
|
+
|
|
40
|
+
// horizonal pass
|
|
41
|
+
for (let y = 0; y < height; y++) {
|
|
42
|
+
for (let x = 0; x < width; x++) {
|
|
43
|
+
sample.fill(0)
|
|
44
|
+
|
|
45
|
+
for (let ix = 0; ix < sample_count; ix++) {
|
|
46
|
+
|
|
47
|
+
const local_x = ix - half_samples;
|
|
48
|
+
|
|
49
|
+
const sample_x = x + local_x * local_u_scale;
|
|
50
|
+
|
|
51
|
+
const power = kernel[ix];
|
|
52
|
+
|
|
53
|
+
for (let i = 0; i < channel_count; i++) {
|
|
54
|
+
const channel_value = source.sampleChannelBilinear(sample_x, y, i);
|
|
55
|
+
|
|
56
|
+
sample[i] += channel_value * power;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
target.write(x, y, sample);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
source = target;
|
|
66
|
+
|
|
67
|
+
// vertical pass
|
|
68
|
+
for (let y = 0; y < height; y++) {
|
|
69
|
+
for (let x = 0; x < width; x++) {
|
|
70
|
+
sample.fill(0)
|
|
71
|
+
|
|
72
|
+
for (let iy = 0; iy < sample_count; iy++) {
|
|
73
|
+
|
|
74
|
+
const local_y = iy - half_samples;
|
|
75
|
+
|
|
76
|
+
const sample_y = x + local_y * local_v_scale;
|
|
77
|
+
|
|
78
|
+
const power = kernel[iy];
|
|
79
|
+
|
|
80
|
+
for (let i = 0; i < channel_count; i++) {
|
|
81
|
+
const channel_value = source.sampleChannelBilinear(x, sample_y, i);
|
|
82
|
+
|
|
83
|
+
sample[i] += channel_value * power;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
target.write(x, y, sample);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CellFilterGaussianBlur.d.ts","sourceRoot":"","sources":["../../../../../../src/generation/filtering/numeric/complex/CellFilterGaussianBlur.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CellFilterGaussianBlur.d.ts","sourceRoot":"","sources":["../../../../../../src/generation/filtering/numeric/complex/CellFilterGaussianBlur.js"],"names":[],"mappings":"AAkDA;IAiFI;;;;;;;OAOG;IACH,oBANW,UAAU,KACV,MAAM,KACN,MAAM,YACN,MAAM,GACJ,sBAAsB,CAclC;IAjGG,kBAAkB;IAClB,kBAAkB;IAElB,gBAAiB;IACjB,gBAAiB;IAEjB;;;OAGG;IACH,QAFU,UAAU,CAEF;IAElB,eAAe;IACf,eAAe;IAEf;;;;OAIG;IACH,iBAAkB;IAElB;;;;OAIG;IACH,6BAA6B;IAE7B;;;;OAIG;IACH,iCAAiC;IAEjC;;;;OAIG;IACH,wBAAwB;IAExB;;;;OAIG;IACH,wBAAwB;IAG5B,uCAuBC;IAyBD,0DA6CC;CACJ;2BAnM0B,qBAAqB"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { assert } from "../../../../core/assert.js";
|
|
2
2
|
import { gaussian } from "../../../../core/math/gaussian.js";
|
|
3
|
+
import { makeNextOdd } from "../../../../core/math/makeNextOdd.js";
|
|
3
4
|
import { max2 } from "../../../../core/math/max2.js";
|
|
4
|
-
import {
|
|
5
|
+
import { CellFilter } from "../../CellFilter.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Build gaussian 2d kernel
|
|
@@ -47,22 +48,6 @@ function buildKernel(result, samplesX, samplesY, sigma_x, sigma_y) {
|
|
|
47
48
|
return powerTotal;
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
/**
|
|
51
|
-
*
|
|
52
|
-
* even number of samples, make odd to ensure we sample reference point
|
|
53
|
-
* @param {number} x
|
|
54
|
-
* @return {number}
|
|
55
|
-
*/
|
|
56
|
-
function makeNextOdd(x) {
|
|
57
|
-
if (x % 2 === 0) {
|
|
58
|
-
// even, make odd
|
|
59
|
-
return x + 1;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// already odd
|
|
63
|
-
return x;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
51
|
export class CellFilterGaussianBlur extends CellFilter {
|
|
67
52
|
constructor() {
|
|
68
53
|
super();
|