@woosh/meep-engine 2.48.12 → 2.48.14
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/package.json +1 -1
- package/src/core/collection/queue/Deque.d.ts +9 -0
- package/src/core/collection/queue/Deque.js +3 -0
- package/src/core/collection/queue/Deque.spec.js +51 -0
- package/src/core/font/FontAssetLoader.js +2 -2
- package/src/core/math/bessel_3.js +3 -1
- package/src/core/math/noise/create_noise_2d.js +193 -0
- package/src/core/path/computeFileExtension.js +3 -2
- package/src/engine/Engine.js +14 -8
- package/src/engine/achievements/AchievementManager.js +16 -16
- package/src/engine/asset/AssetManager.d.ts +10 -5
- package/src/engine/asset/AssetManager.js +79 -24
- package/src/engine/asset/AssetManager.spec.js +1 -1
- package/src/engine/asset/AssetRequest.js +19 -1
- package/src/engine/asset/AssetRequestScope.d.ts +3 -0
- package/src/engine/asset/AssetRequestScope.js +64 -0
- package/src/engine/asset/PendingAsset.js +7 -7
- package/src/engine/asset/loaders/ArrayBufferLoader.js +1 -1
- package/src/engine/asset/loaders/AssetLoader.d.ts +9 -2
- package/src/engine/asset/loaders/AssetLoader.js +19 -16
- package/src/engine/asset/loaders/GLTFAssetLoader.d.ts +1 -1
- package/src/engine/asset/loaders/GLTFAssetLoader.js +2 -2
- package/src/engine/asset/loaders/JavascriptAssetLoader.js +17 -12
- package/src/engine/asset/loaders/JsonAssetLoader.js +1 -1
- package/src/engine/asset/loaders/LegacyThreeJSONAssetLoader.js +4 -1
- package/src/engine/asset/loaders/SVGAssetLoader.js +1 -1
- package/src/engine/asset/loaders/SoundAssetLoader.js +4 -6
- package/src/engine/asset/loaders/TextAssetLoader.js +1 -1
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +24 -17
- package/src/engine/asset/loaders/texture/TextureAssetLoader.d.ts +1 -1
- package/src/engine/asset/loaders/texture/TextureAssetLoader.js +1 -1
- package/src/engine/asset/preloader/Preloader.js +1 -1
- package/src/engine/development/performance/MetricStatistics.js +7 -5
- package/src/engine/development/performance/RingBufferMetric.js +2 -2
- package/src/engine/ecs/foliage/ecs/Foliage2System.js +7 -5
- package/src/engine/ecs/foliage/ecs/InstancedMeshUtils.js +14 -1
- package/src/engine/ecs/gui/GUIElementSystem.d.ts +1 -1
- package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.js +2 -2
- package/src/engine/ecs/terrain/ecs/PromiseSamplerHeight.js +16 -9
- package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +3 -21
- package/src/engine/ecs/terrain/ecs/splat/SplatMapping.js +16 -11
- package/src/engine/ecs/terrain/serialization/TerrainSerializationAdapter.js +1 -1
- package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.js +18 -15
- package/src/engine/graphics/ecs/camera/pp/PerfectPanner.js +4 -2
- package/src/engine/graphics/ecs/mesh/MeshSystem.js +1 -1
- package/src/engine/graphics/ecs/path/tube/build/TubePathBuilder.js +6 -4
- package/src/engine/graphics/material/getTextureImmediate.js +5 -3
- package/src/engine/graphics/texture/3d/SingleChannelSampler3D.js +146 -0
- package/src/engine/graphics/texture/3d/scs3d_read_2d_slice.js +26 -0
- package/src/engine/graphics/texture/atlas/ManagedTextureAtlas.js +1 -1
- package/src/engine/graphics/texture/sampler/Sampler2D.js +22 -13
- package/src/engine/graphics/texture/sampler/filter/box.js +3 -3
- package/src/engine/graphics/texture/sampler/filter/kaiser_bessel_window.js +2 -1
- package/src/engine/graphics/texture/sampler/genericResampleSampler2D.js +9 -8
- package/src/engine/graphics/texture/sampler/loadSampler2D.js +18 -16
- package/src/engine/graphics/texture/sampler/sampler2d_scale_down_linear.js +8 -11
- package/src/engine/graphics/texture/virtual/tile/TileLoader.js +1 -1
- package/src/engine/graphics/trail/x/RibbonXPlugin.js +5 -3
- package/src/engine/knowledge/database/StaticKnowledgeDataTable.js +1 -1
- package/src/engine/physics/fluid/FluidField.js +153 -1
- package/src/engine/physics/fluid/prototype.js +201 -0
- package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.js +67 -0
- package/src/engine/sound/ecs/emitter/loadSoundTrackAsset.js +1 -1
- package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +17 -12
- package/src/generation/filtering/numeric/complex/CellFilterSimplexNoise.js +14 -10
- package/src/view/elements/MeshPreview.js +66 -64
- package/src/view/elements/image/SvgImageView.js +8 -6
- package/src/view/renderModel.js +1 -1
|
@@ -115,9 +115,11 @@ export class RibbonXPlugin extends EnginePlugin {
|
|
|
115
115
|
if (spec.diffuse !== null) {
|
|
116
116
|
const am = this.engine.assetManager;
|
|
117
117
|
|
|
118
|
-
am.get(
|
|
119
|
-
|
|
120
|
-
|
|
118
|
+
am.get({
|
|
119
|
+
path: spec.diffuse, type: GameAssetType.Texture, callback: (asset) => {
|
|
120
|
+
material.uniforms.uDiffuse.value = asset.create();
|
|
121
|
+
}, failure: console.warn
|
|
122
|
+
});
|
|
121
123
|
|
|
122
124
|
material.defines.USE_TEXTURE = true;
|
|
123
125
|
}
|
|
@@ -1,9 +1,161 @@
|
|
|
1
|
+
import { clamp } from "../../../core/math/clamp.js";
|
|
2
|
+
import { lerp } from "../../../core/math/lerp.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {Float32Array} data
|
|
7
|
+
* @param {number[]} resolution
|
|
8
|
+
*/
|
|
9
|
+
function v3_grid_apply_advection_forward(data, resolution) {
|
|
10
|
+
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @param {Float32Array} data
|
|
16
|
+
* @param {number[]} resolution
|
|
17
|
+
*/
|
|
18
|
+
function v3_grid_apply_advection_reverse(data, resolution) {
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
1
22
|
/**
|
|
2
23
|
* Represents a space where fluid simulation happens
|
|
3
24
|
*
|
|
4
25
|
* @see 2019 GDC talk by Runard Rupert "Wind Simulation in God of War" https://www.youtube.com/watch?v=dDgyBKkSf7A
|
|
5
26
|
* @see Inspired by GDC talk "Interactive Wind and Vegetation in 'God of War'" - https://www.youtube.com/watch?v=MKX45_riWQA
|
|
6
27
|
*/
|
|
7
|
-
export class FluidField{
|
|
28
|
+
export class FluidField {
|
|
29
|
+
data = new Float32Array(0)
|
|
30
|
+
#size = [0, 0, 0]
|
|
31
|
+
#resolution = [0, 0, 0]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
build() {
|
|
35
|
+
this.data = new Float32Array(
|
|
36
|
+
this.#resolution[0] * this.#resolution[1] * this.#resolution[2] * 3
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
* @param {number[]} out
|
|
43
|
+
* @param {number} u
|
|
44
|
+
* @param {number} v
|
|
45
|
+
* @param {number} w
|
|
46
|
+
*/
|
|
47
|
+
sample_linear_uv(out, u, v, w) {
|
|
48
|
+
const max_x = this.#resolution[0] - 1;
|
|
49
|
+
const max_y = this.#resolution[1] - 1;
|
|
50
|
+
const max_z = this.#resolution[2] - 1;
|
|
51
|
+
|
|
52
|
+
this.sample_linear(out, u * max_x, v * max_y, w * max_z);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
*
|
|
57
|
+
* @param {number[]} out
|
|
58
|
+
* @param {number} x
|
|
59
|
+
* @param {number} y
|
|
60
|
+
* @param {number} z
|
|
61
|
+
*/
|
|
62
|
+
sample_linear(out, x, y, z) {
|
|
63
|
+
out[0] = this.sample_channel_linear(x, y, z, 0);
|
|
64
|
+
out[1] = this.sample_channel_linear(x, y, z, 1);
|
|
65
|
+
out[2] = this.sample_channel_linear(x, y, z, 2);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
*
|
|
70
|
+
* @param {number} x
|
|
71
|
+
* @param {number} y
|
|
72
|
+
* @param {number} z
|
|
73
|
+
* @param {number} channel
|
|
74
|
+
* @returns {number}
|
|
75
|
+
*/
|
|
76
|
+
sample_channel_linear(x, y, z, channel) {
|
|
77
|
+
const resolution = this.#resolution;
|
|
78
|
+
|
|
79
|
+
const res_x = resolution[0];
|
|
80
|
+
const res_y = resolution[1];
|
|
81
|
+
const res_z = resolution[2];
|
|
82
|
+
|
|
83
|
+
const x_max = res_x - 1;
|
|
84
|
+
const y_max = res_y - 1;
|
|
85
|
+
const z_max = res_z - 1;
|
|
86
|
+
|
|
87
|
+
const x_clamped = clamp(x, 0, x_max);
|
|
88
|
+
const y_clamped = clamp(y, 0, y_max);
|
|
89
|
+
const z_clamped = clamp(z, 0, z_max);
|
|
90
|
+
|
|
91
|
+
const x0 = x_clamped | 0;
|
|
92
|
+
const y0 = y_clamped | 0;
|
|
93
|
+
const z0 = z_clamped | 0;
|
|
94
|
+
|
|
95
|
+
const f_x = x_clamped - x0;
|
|
96
|
+
const f_y = y_clamped - y0;
|
|
97
|
+
const f_z = z_clamped - z0;
|
|
98
|
+
|
|
99
|
+
const x1 = x_clamped === x0 ? x0 : x0 + 1;
|
|
100
|
+
const y1 = y_clamped === y0 ? y0 : y0 + 1;
|
|
101
|
+
const z1 = z_clamped === z0 ? z0 : z0 + 1;
|
|
102
|
+
|
|
103
|
+
// get 8 points
|
|
104
|
+
const data = this.data;
|
|
105
|
+
|
|
106
|
+
const z0_offset = z0 * (res_x * res_y) * 3;
|
|
107
|
+
|
|
108
|
+
const y0_offset = y0 * res_x * 3;
|
|
109
|
+
|
|
110
|
+
const x0_offset = x0 * 3 + channel;
|
|
111
|
+
const x1_offset = x1 * 3 + channel;
|
|
112
|
+
|
|
113
|
+
const x0y0z0 = data[z0_offset + y0_offset + x0_offset];
|
|
114
|
+
const x1y0z0 = data[z0_offset + y0_offset + x1_offset];
|
|
115
|
+
|
|
116
|
+
const y1_offset = y1 * res_x * 3;
|
|
117
|
+
|
|
118
|
+
const x0y1z0 = data[z0_offset + y1_offset + x0_offset];
|
|
119
|
+
const x1y1z0 = data[z0_offset + y1_offset + x1_offset];
|
|
120
|
+
|
|
121
|
+
const z1_offset = z1 * (res_x * res_y) * 3;
|
|
122
|
+
|
|
123
|
+
const x0y0z1 = data[z1_offset + y0_offset + x0_offset];
|
|
124
|
+
const x1y0z1 = data[z1_offset + y0_offset + x1_offset];
|
|
125
|
+
|
|
126
|
+
const x0y1z1 = data[z1_offset + y1_offset + x0_offset];
|
|
127
|
+
const x1y1z1 = data[z1_offset + y1_offset + x1_offset];
|
|
128
|
+
|
|
129
|
+
// filter on z0
|
|
130
|
+
const lerp_z0_y0 = lerp(x0y0z0, x1y0z0, f_x);
|
|
131
|
+
const lerp_z0_y1 = lerp(x0y1z0, x1y1z0, f_x);
|
|
132
|
+
const lerp_z0 = lerp(lerp_z0_y0, lerp_z0_y1, f_y);
|
|
133
|
+
|
|
134
|
+
// filter on z1
|
|
135
|
+
const lerp_z1_y0 = lerp(x0y0z1, x1y0z1, f_x);
|
|
136
|
+
const lerp_z1_y1 = lerp(x0y1z1, x1y1z1, f_x);
|
|
137
|
+
const lerp_z1 = lerp(lerp_z1_y0, lerp_z1_y1, f_y);
|
|
138
|
+
|
|
139
|
+
return lerp(lerp_z0, lerp_z1, f_z);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
set size(v) {
|
|
143
|
+
const width = v[0];
|
|
144
|
+
const height = v[1];
|
|
145
|
+
const depth = v[2];
|
|
146
|
+
|
|
147
|
+
this.#size[0] = width;
|
|
148
|
+
this.#size[1] = height;
|
|
149
|
+
this.#size[2] = depth
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
set resolution(v) {
|
|
153
|
+
const width = v[0];
|
|
154
|
+
const height = v[1];
|
|
155
|
+
const depth = v[2];
|
|
8
156
|
|
|
157
|
+
this.#resolution[0] = width;
|
|
158
|
+
this.#resolution[1] = height;
|
|
159
|
+
this.#resolution[2] = depth
|
|
160
|
+
}
|
|
9
161
|
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { EngineHarness } from "../../EngineHarness.js";
|
|
2
|
+
import { SingleChannelSampler3D } from "../../graphics/texture/3d/SingleChannelSampler3D.js";
|
|
3
|
+
import GUIElementSystem from "../../ecs/gui/GUIElementSystem.js";
|
|
4
|
+
import EntityBuilder from "../../ecs/EntityBuilder.js";
|
|
5
|
+
import GUIElement from "../../ecs/gui/GUIElement.js";
|
|
6
|
+
import EmptyView from "../../../view/elements/EmptyView.js";
|
|
7
|
+
import { Sampler2D } from "../../graphics/texture/sampler/Sampler2D.js";
|
|
8
|
+
import { CanvasView } from "../../../view/elements/CanvasView.js";
|
|
9
|
+
import { float2uint8 } from "../../../core/binary/float2uint8.js";
|
|
10
|
+
import { clamp } from "../../../core/math/clamp.js";
|
|
11
|
+
import { randomIntegerBetween } from "../../../core/math/random/randomIntegerBetween.js";
|
|
12
|
+
import { seededRandom } from "../../../core/math/random/seededRandom.js";
|
|
13
|
+
import { BehaviorComponent } from "../../intelligence/behavior/ecs/BehaviorComponent.js";
|
|
14
|
+
import { BehaviorSystem } from "../../intelligence/behavior/ecs/BehaviorSystem.js";
|
|
15
|
+
import { v3_grid_apply_diffusion } from "./solver/v3_grid_apply_diffusion.js";
|
|
16
|
+
import { max2 } from "../../../core/math/max2.js";
|
|
17
|
+
import { MetricCollection } from "../../development/performance/MetricCollection.js";
|
|
18
|
+
import { PeriodicConsolePrinter } from "../../development/performance/monitor/PeriodicConsolePrinter.js";
|
|
19
|
+
import { MetricStatistics } from "../../development/performance/MetricStatistics.js";
|
|
20
|
+
|
|
21
|
+
const harness = new EngineHarness();
|
|
22
|
+
|
|
23
|
+
class SliceVisualiser extends EmptyView {
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
*
|
|
27
|
+
* @param {SingleChannelSampler3D} source
|
|
28
|
+
*/
|
|
29
|
+
constructor(source) {
|
|
30
|
+
super({ classList: ['slice-visualizer'] });
|
|
31
|
+
|
|
32
|
+
this.source = source;
|
|
33
|
+
|
|
34
|
+
const slices = [];
|
|
35
|
+
const views = [];
|
|
36
|
+
|
|
37
|
+
const resolution = source.resolution;
|
|
38
|
+
const resolution_x = resolution[0];
|
|
39
|
+
const resolution_y = resolution[1];
|
|
40
|
+
const resolution_z = resolution[2];
|
|
41
|
+
|
|
42
|
+
const slice_size = resolution_x * resolution_y;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* @type {ImageData|null}
|
|
47
|
+
*/
|
|
48
|
+
let imageData = null;
|
|
49
|
+
|
|
50
|
+
for (let i = 0; i < resolution_z; i++) {
|
|
51
|
+
slices[i] = new Sampler2D(new Float32Array(source.data.buffer, i * slice_size * 4, slice_size), 1, resolution_x, resolution_y);
|
|
52
|
+
|
|
53
|
+
const child = new CanvasView();
|
|
54
|
+
child.size.set(resolution_x, resolution_y);
|
|
55
|
+
|
|
56
|
+
if (imageData === null) {
|
|
57
|
+
imageData = child.context2d.getImageData(0, 0, resolution_x, resolution_y);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
child.css({
|
|
61
|
+
position: "absolute",
|
|
62
|
+
left: 0,
|
|
63
|
+
top: 0
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
views[i] = child;
|
|
67
|
+
|
|
68
|
+
this.addChild(child);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
this.draw = () => {
|
|
72
|
+
|
|
73
|
+
for (let i = 0; i < resolution_z; i++) {
|
|
74
|
+
const view = views[i];
|
|
75
|
+
const slice = slices[i];
|
|
76
|
+
|
|
77
|
+
for (let j = 0; j < slice_size; j++) {
|
|
78
|
+
const j4 = j * 4;
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
const uint8_value = float2uint8(slice.data[j]);
|
|
82
|
+
|
|
83
|
+
imageData.data[j4] = clamp(uint8_value, 0, 255);
|
|
84
|
+
imageData.data[j4 + 3] = 255;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
view.context2d.putImageData(imageData, 0, 0);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const layout = () => {
|
|
93
|
+
const width = this.size.x;
|
|
94
|
+
|
|
95
|
+
const grid_width = max2(1, Math.floor(width / resolution_x));
|
|
96
|
+
|
|
97
|
+
for (let i = 0; i < resolution_z; i++) {
|
|
98
|
+
const view = views[i];
|
|
99
|
+
|
|
100
|
+
const grid_x = i % grid_width;
|
|
101
|
+
const grid_y = Math.floor(i / grid_width);
|
|
102
|
+
|
|
103
|
+
view.position.set(grid_x * resolution_x, grid_y * resolution_y);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
this.on.linked.add(layout);
|
|
108
|
+
this.size.onChanged.add(layout);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const metrics = new MetricCollection();
|
|
115
|
+
|
|
116
|
+
metrics.create({ name: 'sim' })
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
*
|
|
120
|
+
* @param {Engine} engine
|
|
121
|
+
*/
|
|
122
|
+
function main(engine) {
|
|
123
|
+
|
|
124
|
+
const ecd = engine.entityManager.dataset;
|
|
125
|
+
|
|
126
|
+
const sampler = new SingleChannelSampler3D();
|
|
127
|
+
|
|
128
|
+
sampler.resolution = [32, 32, 16];
|
|
129
|
+
|
|
130
|
+
const random = seededRandom();
|
|
131
|
+
|
|
132
|
+
sampler.data.fill(1000, 20, 40);
|
|
133
|
+
|
|
134
|
+
for (let i = 0; i < 100; i++) {
|
|
135
|
+
|
|
136
|
+
sampler.write(
|
|
137
|
+
randomIntegerBetween(random, 0, 16),
|
|
138
|
+
randomIntegerBetween(random, 0, 16),
|
|
139
|
+
randomIntegerBetween(random, 0, 4),
|
|
140
|
+
random()
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
const slice_view = new SliceVisualiser(sampler);
|
|
147
|
+
|
|
148
|
+
slice_view.size.set(432, 1000);
|
|
149
|
+
slice_view.scale.setScalar(2);
|
|
150
|
+
slice_view.transformOrigin.set(0, 0);
|
|
151
|
+
|
|
152
|
+
const sampler_0 = sampler.clone();
|
|
153
|
+
const sampler_1 = sampler.clone();
|
|
154
|
+
|
|
155
|
+
const ping_pong = [sampler_0, sampler_1];
|
|
156
|
+
let ping_pong_index = 0;
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
new EntityBuilder()
|
|
160
|
+
.add(BehaviorComponent.looping_function(time_delta => {
|
|
161
|
+
|
|
162
|
+
const source = ping_pong[ping_pong_index % 2];
|
|
163
|
+
const target = ping_pong[(ping_pong_index + 1) % 2];
|
|
164
|
+
|
|
165
|
+
ping_pong_index++;
|
|
166
|
+
|
|
167
|
+
const t0 = performance.now();
|
|
168
|
+
|
|
169
|
+
for (let i = 0; i < 5; i++) {
|
|
170
|
+
v3_grid_apply_diffusion(target.data, source.data, source.resolution);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
metrics.get('sim').record(performance.now() - t0);
|
|
174
|
+
|
|
175
|
+
sampler.copy(target);
|
|
176
|
+
|
|
177
|
+
slice_view.draw();
|
|
178
|
+
|
|
179
|
+
}))
|
|
180
|
+
.build(ecd);
|
|
181
|
+
|
|
182
|
+
const metric_stats = new MetricStatistics();
|
|
183
|
+
|
|
184
|
+
new PeriodicConsolePrinter(3, () => metrics.list().map(m => {
|
|
185
|
+
metrics.get(m).computeStats(metric_stats);
|
|
186
|
+
|
|
187
|
+
return `${m}: ${metric_stats}`;
|
|
188
|
+
}).join('\n')).start()
|
|
189
|
+
|
|
190
|
+
new EntityBuilder()
|
|
191
|
+
.add(GUIElement.fromView(slice_view))
|
|
192
|
+
.build(ecd);
|
|
193
|
+
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
harness.initialize({
|
|
197
|
+
configuration(config, engine) {
|
|
198
|
+
config.addSystem(new GUIElementSystem(engine.gameView, engine))
|
|
199
|
+
config.addSystem(new BehaviorSystem(engine))
|
|
200
|
+
}
|
|
201
|
+
}).then(main)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {Float32Array} output
|
|
4
|
+
* @param {Float32Array} input
|
|
5
|
+
* @param {number[]} resolution
|
|
6
|
+
*/
|
|
7
|
+
export function v3_grid_apply_diffusion(output, input, resolution) {
|
|
8
|
+
const res_x = resolution[0];
|
|
9
|
+
const res_y = resolution[1];
|
|
10
|
+
const res_z = resolution[2];
|
|
11
|
+
|
|
12
|
+
const factor = 1 / 7;
|
|
13
|
+
|
|
14
|
+
let sum = 0;
|
|
15
|
+
|
|
16
|
+
const slice_size = res_y * res_x;
|
|
17
|
+
|
|
18
|
+
for (let z = 0; z < res_z; z++) {
|
|
19
|
+
for (let y = 0; y < res_y; y++) {
|
|
20
|
+
for (let x = 0; x < res_x; x++) {
|
|
21
|
+
|
|
22
|
+
let sample_count = 1;
|
|
23
|
+
|
|
24
|
+
sum = 0;
|
|
25
|
+
|
|
26
|
+
// sample cells around
|
|
27
|
+
if (z > 0) {
|
|
28
|
+
sample_count++;
|
|
29
|
+
sum += input[(z - 1) * slice_size + y * res_x + x]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (y > 0) {
|
|
33
|
+
sample_count++;
|
|
34
|
+
sum += input[z * slice_size + (y - 1) * res_x + x]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (x > 0) {
|
|
38
|
+
sample_count++;
|
|
39
|
+
sum += input[z * slice_size + y * res_x + (x - 1)]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
const current = z * slice_size + y * res_x + x;
|
|
44
|
+
|
|
45
|
+
sum += input[current];
|
|
46
|
+
|
|
47
|
+
if (x < res_x - 1) {
|
|
48
|
+
sample_count++;
|
|
49
|
+
sum += input[z * slice_size + y * res_x + (x + 1)]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (y < res_y - 1) {
|
|
53
|
+
sample_count++;
|
|
54
|
+
sum += input[z * slice_size + (y + 1) * res_x + x]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (z < res_z - 1) {
|
|
58
|
+
sample_count++;
|
|
59
|
+
sum += input[(z + 1) * slice_size + y * res_x + x]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
output[current] = sum / sample_count;
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -37,5 +37,5 @@ export function loadSoundTrackAsset(track, assetManager, resolve = noop, reject
|
|
|
37
37
|
asset_path = track_url;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
assetManager.get(asset_path, GameAssetType.Sound, resolve, reject);
|
|
40
|
+
assetManager.get({ path: asset_path, type: GameAssetType.Sound, callback: resolve, failure: reject });
|
|
41
41
|
}
|
|
@@ -72,12 +72,20 @@ export class CellFilterGaussianBlur extends CellFilter {
|
|
|
72
72
|
* @private
|
|
73
73
|
*/
|
|
74
74
|
this.__kernel = [];
|
|
75
|
+
|
|
75
76
|
/**
|
|
76
77
|
*
|
|
77
78
|
* @type {number}
|
|
78
79
|
* @private
|
|
79
80
|
*/
|
|
80
81
|
this.__kernel_total_power = 0;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
*
|
|
85
|
+
* @type {number}
|
|
86
|
+
* @private
|
|
87
|
+
*/
|
|
88
|
+
this.__inv_kernel_total_power = 0;
|
|
81
89
|
}
|
|
82
90
|
|
|
83
91
|
initialize(grid, seed) {
|
|
@@ -94,6 +102,9 @@ export class CellFilterGaussianBlur extends CellFilter {
|
|
|
94
102
|
// initialize kernel
|
|
95
103
|
this.__kernel_total_power = buildKernel(this.__kernel, this.samples_x, this.samples_y, this.sigma_x, this.sigma_y);
|
|
96
104
|
|
|
105
|
+
// store inverse, to be able to use multiply instead of division in execution
|
|
106
|
+
this.__inv_kernel_total_power = 1 / this.__kernel_total_power;
|
|
107
|
+
|
|
97
108
|
super.initialize(grid, seed);
|
|
98
109
|
}
|
|
99
110
|
|
|
@@ -132,8 +143,8 @@ export class CellFilterGaussianBlur extends CellFilter {
|
|
|
132
143
|
const sizeX = this.size_x;
|
|
133
144
|
const sizeY = this.size_y;
|
|
134
145
|
|
|
135
|
-
const local_u_scale =
|
|
136
|
-
const local_v_scale =
|
|
146
|
+
const local_u_scale = sizeX / (samplesX - 1);
|
|
147
|
+
const local_v_scale = sizeY / (samplesY - 1);
|
|
137
148
|
|
|
138
149
|
let sum = 0;
|
|
139
150
|
let ix, iy = 0;
|
|
@@ -146,9 +157,7 @@ export class CellFilterGaussianBlur extends CellFilter {
|
|
|
146
157
|
for (; iy < samplesY; iy++) {
|
|
147
158
|
const local_y = iy - half_samples_y;
|
|
148
159
|
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
const offset_y = sizeY * ny;
|
|
160
|
+
const offset_y = y + local_y * local_v_scale;
|
|
152
161
|
|
|
153
162
|
const row_address = iy * i_samples_x;
|
|
154
163
|
|
|
@@ -156,13 +165,11 @@ export class CellFilterGaussianBlur extends CellFilter {
|
|
|
156
165
|
|
|
157
166
|
const local_x = ix - half_samples_x;
|
|
158
167
|
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
const offset_x = sizeX * nx;
|
|
168
|
+
const offset_x = local_x * local_u_scale;
|
|
162
169
|
|
|
163
170
|
const power = kernel[row_address + ix];
|
|
164
171
|
|
|
165
|
-
const sourceValue = source.execute(grid, x + offset_x,
|
|
172
|
+
const sourceValue = source.execute(grid, x + offset_x, offset_y, 0);
|
|
166
173
|
|
|
167
174
|
const sample_contribution = sourceValue * power;
|
|
168
175
|
|
|
@@ -171,8 +178,6 @@ export class CellFilterGaussianBlur extends CellFilter {
|
|
|
171
178
|
}
|
|
172
179
|
}
|
|
173
180
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
return result;
|
|
181
|
+
return sum * this.__inv_kernel_total_power;
|
|
177
182
|
}
|
|
178
183
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { seededRandom } from "../../../../core/math/random/seededRandom.js";
|
|
2
2
|
import { CellFilter } from "../../CellFilter.js";
|
|
3
|
-
import SimplexNoise from "simplex-noise";
|
|
4
3
|
import { CellFilterAdd } from "../math/algebra/CellFilterAdd.js";
|
|
5
4
|
import { CellFilterMultiply } from "../math/algebra/CellFilterMultiply.js";
|
|
6
5
|
import { CellFilterLiteralFloat } from "../CellFilterLiteralFloat.js";
|
|
7
6
|
import { CellFilterDivide } from "../math/algebra/CellFilterDivide.js";
|
|
7
|
+
import { createNoise2D } from "../../../../core/math/noise/create_noise_2d.js";
|
|
8
8
|
|
|
9
9
|
export class CellFilterSimplexNoise extends CellFilter {
|
|
10
10
|
constructor() {
|
|
@@ -12,7 +12,7 @@ export class CellFilterSimplexNoise extends CellFilter {
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* @private
|
|
15
|
-
* @type {
|
|
15
|
+
* @type {function(x:number,y:number):number}
|
|
16
16
|
*/
|
|
17
17
|
this.noise = null;
|
|
18
18
|
|
|
@@ -25,6 +25,9 @@ export class CellFilterSimplexNoise extends CellFilter {
|
|
|
25
25
|
this.scale_x = 1;
|
|
26
26
|
this.scale_y = 1;
|
|
27
27
|
|
|
28
|
+
this.inv_scale_x = 1;
|
|
29
|
+
this.inv_scale_y = 1;
|
|
30
|
+
|
|
28
31
|
/**
|
|
29
32
|
* RNG Seed offset
|
|
30
33
|
* @type {number}
|
|
@@ -50,6 +53,8 @@ export class CellFilterSimplexNoise extends CellFilter {
|
|
|
50
53
|
let amplitude = 1;
|
|
51
54
|
let totalAmplitude = 0;
|
|
52
55
|
|
|
56
|
+
const G = Math.pow(2, -persistence);
|
|
57
|
+
|
|
53
58
|
for (let i = 0; i < octaves; i++) {
|
|
54
59
|
const noise = CellFilterSimplexNoise.from(scale * frequency, scale * frequency, s);
|
|
55
60
|
|
|
@@ -63,7 +68,7 @@ export class CellFilterSimplexNoise extends CellFilter {
|
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
totalAmplitude += amplitude;
|
|
66
|
-
amplitude *=
|
|
71
|
+
amplitude *= G;
|
|
67
72
|
frequency *= lacunarity;
|
|
68
73
|
|
|
69
74
|
s = (s + 1) * 31;
|
|
@@ -95,25 +100,24 @@ export class CellFilterSimplexNoise extends CellFilter {
|
|
|
95
100
|
r.scale_y = scale_y;
|
|
96
101
|
r.__seed = seed;
|
|
97
102
|
|
|
103
|
+
r.inv_scale_x = 1 / scale_x;
|
|
104
|
+
r.inv_scale_y = 1 / scale_y;
|
|
105
|
+
|
|
98
106
|
return r;
|
|
99
107
|
}
|
|
100
108
|
|
|
101
109
|
initialize(grid, seed) {
|
|
102
110
|
this.random.setCurrentSeed(seed + this.__seed);
|
|
103
111
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
this.noise = noise;
|
|
112
|
+
this.noise = createNoise2D(this.random);
|
|
107
113
|
|
|
108
114
|
super.initialize(grid, seed);
|
|
109
115
|
}
|
|
110
116
|
|
|
111
117
|
execute(grid, x, y, rotation) {
|
|
112
|
-
const noiseValue = this.noise
|
|
118
|
+
const noiseValue = this.noise(x * this.inv_scale_x, y * this.inv_scale_y);
|
|
113
119
|
|
|
114
120
|
//noise function returns values in range [-1,1] we need to scale that to [0,1] range
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return normalizedValue;
|
|
121
|
+
return (noiseValue + 1) * 0.5;
|
|
118
122
|
}
|
|
119
123
|
}
|