@woosh/meep-engine 2.42.8 → 2.43.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.
- package/core/binary/BitSet.js +4 -4
- package/core/binary/ctz32.js +40 -0
- package/core/collection/ObservedMap.js +61 -57
- package/core/collection/heap/FastBinaryHeap.js +7 -1
- package/core/collection/heap/Uint32Heap.js +19 -0
- package/core/collection/map/AsyncLoadingCache.js +3 -1
- package/core/geom/2d/compute_polygon_area_2d.js +32 -0
- package/core/geom/2d/compute_polygon_area_2d.spec.js +10 -0
- package/core/geom/2d/compute_triangle_area_2d.js +15 -0
- package/core/geom/2d/compute_triangle_area_2d.spec.js +9 -0
- package/core/geom/2d/convex-hull/convex_hull_jarvis_2d.js +64 -0
- package/core/geom/2d/convex-hull/convex_hull_jarvis_2d.spec.js +33 -0
- package/core/geom/2d/convex-hull/convex_hull_monotone_2d.js +82 -0
- package/core/geom/2d/convex-hull/fixed_convex_hull_humus.js +135 -0
- package/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +282 -0
- package/core/geom/2d/convex-hull/orientation3.js +444 -0
- package/core/geom/2d/convex-hull/orientation3_array.js +22 -0
- package/core/geom/2d/convex-hull/orientation3_v2.js +12 -0
- package/core/geom/2d/intersect_ray_2d.js +56 -0
- package/core/geom/2d/quad-tree/QuadTreeNode.js +0 -81
- package/core/geom/2d/quad-tree/qt_match_data_by_circle.js +70 -0
- package/core/geom/3d/matrix/m4_multiply_alphatensor.js +131 -0
- package/core/geom/3d/plane/orient3d_fast.js +2 -6
- package/core/geom/3d/tetrahedra/README.md +7 -0
- package/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.js +3 -1
- package/core/geom/3d/tetrahedra/delaunay/Cavity.js +48 -0
- package/core/geom/3d/tetrahedra/{compute_delaunay_tetrahedral_mesh.js → delaunay/compute_delaunay_tetrahedral_mesh.js} +15 -7
- package/core/geom/3d/tetrahedra/{compute_delaunay_tetrahedral_mesh.spec.js → delaunay/compute_delaunay_tetrahedral_mesh.spec.js} +0 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_cavity.js +73 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_walk_toward_cavity.js +48 -0
- package/core/geom/3d/tetrahedra/hxt/a.js +524 -0
- package/core/geom/3d/tetrahedra/hxt/hxt.js +140 -0
- package/core/geom/3d/tetrahedra/hxt/hxt.wasm +0 -0
- package/core/geom/3d/tetrahedra/point_in_tetrahedron_circumsphere.js +35 -20
- package/core/geom/3d/tetrahedra/prototypeTetrahedraBuilder.js +98 -0
- package/core/geom/3d/tetrahedra/tetrahedra_collection.js +60 -131
- package/core/geom/packing/{MaxRectangles.js → max-rect/MaxRectangles.js} +28 -124
- package/core/geom/packing/max-rect/removeRedundantBoxes.js +69 -0
- package/core/geom/packing/max-rect/removeRedundantBoxesArray.js +40 -0
- package/core/geom/v3_distance_above_plane.js +1 -1
- package/core/graph/layout/BoxLayouter.js +2 -88
- package/core/graph/layout/CircleLayout.js +2 -1
- package/core/graph/layout/box/forceIntoBox.js +45 -0
- package/core/graph/layout/box/pullBoxTowardsPoint.js +20 -0
- package/core/graph/layout/box/resolveAABB2Overlap.js +22 -0
- package/core/math/bessel_3.js +11 -0
- package/core/math/bessel_i0.js +26 -0
- package/core/process/executor/ConcurrentExecutor.spec.js +2 -1
- package/core/process/task/util/actionTask.js +19 -0
- package/core/process/task/util/countTask.js +62 -0
- package/core/process/task/util/delayTask.js +45 -0
- package/core/process/task/util/emptyTask.js +19 -0
- package/core/process/task/util/failingTask.js +17 -0
- package/core/process/task/util/futureTask.js +48 -0
- package/core/process/task/util/promiseTask.js +42 -0
- package/core/process/task/util/randomCountTask.js +64 -0
- package/core/process/task/util/wrapTaskIgnoreFailure.js +47 -0
- package/engine/Engine.js +8 -8
- package/engine/EngineBootstrapper.js +1 -1
- package/engine/asset/AssetManager.d.ts +2 -0
- package/engine/asset/AssetManager.js +197 -53
- package/engine/asset/AssetRequest.js +32 -0
- package/engine/asset/loaders/ArrayBufferLoader.js +62 -50
- package/engine/asset/loaders/image/png/PNG.js +15 -1
- package/engine/asset/loaders/image/png/PNGReader.js +3 -2
- package/engine/ecs/foliage/ecs/InstancedMeshUtils.js +2 -1
- package/engine/ecs/storage/BinaryBufferDeSerializer.js +1 -1
- package/engine/ecs/storage/JSONDeSerializer.js +2 -1
- package/engine/ecs/terrain/ecs/splat/SplatMapOptimizer.js +2 -1
- package/engine/ecs/terrain/ecs/splat/SplatMapping.js +1 -1
- package/engine/graphics/camera/makeScreenScissorFrustum.js +1 -1
- package/engine/graphics/camera/testClippingPlaneComputation.js +4 -45
- package/engine/graphics/ecs/camera/FrustumProjector.js +6 -0
- package/engine/graphics/ecs/decal/v2/FPDecalSystem.js +5 -0
- package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +23 -4
- package/engine/graphics/ecs/highlight/plugin/OutlineRenderPlugin.js +1 -1
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +11 -0
- package/engine/graphics/geometry/FULL_SCREEN_TRIANGLE_GEOMETRY.js +1 -2
- package/engine/graphics/impostors/octahedral/ImpostorBaker.js +5 -2
- package/engine/graphics/impostors/octahedral/ImpostorDescription.js +18 -0
- package/engine/graphics/impostors/octahedral/bake/prepare_bake_material.js +15 -0
- package/engine/graphics/impostors/octahedral/prototypeBaker.js +66 -79
- package/engine/graphics/impostors/octahedral/shader/ImpostorShaderWireframeV0.js +134 -0
- package/engine/graphics/impostors/octahedral/util/build_cutout_from_atlas_by_alpha.js +128 -0
- package/engine/graphics/impostors/octahedral/util/build_geometry_from_cutout_shape.js +32 -0
- package/engine/graphics/impostors/octahedral/util/load_mesh_for_bake.js +31 -0
- package/engine/graphics/impostors/octahedral/util/makeImpostorAtlasPreview.js +107 -0
- package/engine/graphics/material/manager/ManagedMaterial.js +4 -0
- package/engine/graphics/material/manager/MaterialManager.js +1 -0
- package/engine/graphics/material/optimization/MaterialOptimizationContext.js +7 -3
- package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +2 -2
- package/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +2 -2
- package/engine/graphics/render/visibility/hiz/buildCanvasViewFromTexture.js +83 -27
- package/engine/graphics/shadows/ShadowMapRenderer.js +11 -4
- package/engine/graphics/texture/atlas/AbstractTextureAtlas.js +2 -1
- package/engine/graphics/texture/atlas/CachingTextureAtlas.js +208 -38
- package/engine/graphics/texture/atlas/TextureAtlas.js +31 -24
- package/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.js +1 -1
- package/engine/graphics/texture/sampler/filter/box.js +16 -0
- package/engine/graphics/texture/sampler/filter/cubic2.js +32 -0
- package/engine/graphics/texture/sampler/filter/gaussian.js +16 -0
- package/engine/graphics/texture/sampler/filter/kaiser_1.js +19 -0
- package/engine/graphics/texture/sampler/filter/kaiser_bessel_window.js +19 -0
- package/engine/graphics/texture/sampler/filter/mitchell.js +55 -0
- package/engine/graphics/texture/sampler/filter/sampler2d_scale_down_generic.js +109 -0
- package/engine/graphics/texture/sampler/filter/triangle.js +19 -0
- package/engine/graphics/texture/sampler/prototypeSamplerFiltering.js +187 -86
- package/engine/graphics/texture/sampler/sampler2_d_scale_down_lanczos.js +77 -25
- package/engine/graphics/texture/sampler/search/make_edge_condition_channel_threshold.js +34 -0
- package/engine/graphics/texture/sampler/search/sampler2d_find_pixels.js +24 -0
- package/engine/graphics/texture/sprite/prototypeSpriteCutoutGeometry.js +212 -0
- package/engine/knowledge/database/StaticKnowledgeDataTable.js +1 -1
- package/engine/navigation/grid/AStar.js +1 -1
- package/engine/scene/Scene.js +1 -1
- package/engine/scene/SerializedScene.js +1 -1
- package/engine/scene/transitionToScene.js +3 -1
- package/generation/example/main.js +1 -1
- package/generation/grid/generation/GridTaskApplyActionToCells.js +1 -1
- package/generation/grid/generation/GridTaskDensityMarkerDistribution.js +1 -1
- package/generation/grid/generation/GridTaskExecuteRuleTimes.js +1 -1
- package/generation/grid/generation/NoopGridTaskGenerator.js +1 -1
- package/generation/grid/generation/discrete/GridTaskCellularAutomata.js +2 -1
- package/generation/grid/generation/discrete/GridTaskConnectRooms.js +1 -1
- package/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +3 -2
- package/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.js +1 -1
- package/generation/grid/generation/grid/GridTaskAddNodesFixed.js +1 -1
- package/generation/grid/generation/road/GridTaskGenerateRoads.js +3 -2
- package/generation/grid/generation/util/buildDistanceMapToObjective.js +1 -1
- package/generation/markers/GridActionRuleSet.js +2 -1
- package/generation/placement/GridCellActionTransformNearbyMarkers.js +2 -4
- package/generation/theme/ThemeEngine.js +4 -1
- package/package.json +1 -1
- package/view/asset/AssetLoaderStatusView.js +5 -5
- package/view/minimap/gl/MinimapTerrainGL.js +1 -2
- package/view/renderModel.js +1 -1
- package/view/tooltip/TooltipView.js +5 -5
- package/core/process/task/TaskUtils.js +0 -352
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @see https://github.com/terifan/ImageResampler/blob/dbc212ce6aaa769bf3c9623cb6ead58ffd51d76c/src/org/terifan/image_resampler/FilterFactory.java#L348
|
|
3
|
+
* @param {number} x
|
|
4
|
+
* @returns {number}
|
|
5
|
+
*/
|
|
6
|
+
export function triangle(x) {
|
|
7
|
+
if (x < -1) {
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
if (x < 0) {
|
|
11
|
+
return 1 + x;
|
|
12
|
+
}
|
|
13
|
+
if (x < 1) {
|
|
14
|
+
return 1 - x;
|
|
15
|
+
}
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
triangle.support = 1;
|
|
@@ -2,18 +2,30 @@ import { EngineHarness } from "../../../EngineHarness.js";
|
|
|
2
2
|
import { ImageRGBADataLoader } from "../../../asset/loaders/image/ImageRGBADataLoader.js";
|
|
3
3
|
import sampler2D2Canvas from "./Sampler2D2Canvas.js";
|
|
4
4
|
import { CanvasView } from "../../../../view/elements/CanvasView.js";
|
|
5
|
-
import { sampler2D_scale_down_lanczos } from "./sampler2_d_scale_down_lanczos.js";
|
|
5
|
+
import { filter_lanczos3, sampler2D_scale_down_lanczos } from "./sampler2_d_scale_down_lanczos.js";
|
|
6
6
|
import { Sampler2D } from "./Sampler2D.js";
|
|
7
7
|
import { genericResampleSampler2D } from "./genericResampleSampler2D.js";
|
|
8
8
|
import Vector2 from "../../../../core/geom/Vector2.js";
|
|
9
9
|
import LabelView from "../../../../view/common/LabelView.js";
|
|
10
10
|
import EmptyView from "../../../../view/elements/EmptyView.js";
|
|
11
11
|
import { sampler2d_downsample_mipmap } from "./resize/sampler2d_downsample_mipmap.js";
|
|
12
|
+
import { kaiser_bessel_window } from "./filter/kaiser_bessel_window.js";
|
|
13
|
+
import { sampler2d_scale_down_generic } from "./filter/sampler2d_scale_down_generic.js";
|
|
14
|
+
import { mitchell, mitchell_v1 } from "./filter/mitchell.js";
|
|
15
|
+
import { kaiser_1 } from "./filter/kaiser_1.js";
|
|
16
|
+
import { triangle } from "./filter/triangle.js";
|
|
17
|
+
import { box } from "./filter/box.js";
|
|
18
|
+
import { gaussian } from "./filter/gaussian.js";
|
|
12
19
|
|
|
13
|
-
function grid(engine, input, transforms, size = new Vector2(input.width, input.height)) {
|
|
20
|
+
function grid({ engine, input, transforms, size = new Vector2(input.width, input.height), display_labels = true }) {
|
|
21
|
+
|
|
22
|
+
const GAP_SIZE = 4;
|
|
14
23
|
|
|
15
24
|
let draw_index = 0;
|
|
16
25
|
|
|
26
|
+
const viewport_width = window.innerWidth;
|
|
27
|
+
const tiles_x = Math.floor(viewport_width / (size.x + GAP_SIZE));
|
|
28
|
+
|
|
17
29
|
for (let i = 0; i < transforms.length; i++) {
|
|
18
30
|
const out = input.clone();
|
|
19
31
|
|
|
@@ -24,21 +36,33 @@ function grid(engine, input, transforms, size = new Vector2(input.width, input.h
|
|
|
24
36
|
skip: false
|
|
25
37
|
};
|
|
26
38
|
|
|
39
|
+
const t0 = performance.now();
|
|
40
|
+
|
|
27
41
|
try {
|
|
28
42
|
transforms[i](out, input, params);
|
|
29
43
|
} catch (e) {
|
|
30
44
|
// error, skip
|
|
45
|
+
console.error(`Failed '${params.label}'. Reason: ${e.message}`)
|
|
31
46
|
}
|
|
32
47
|
|
|
48
|
+
const t1 = performance.now();
|
|
49
|
+
|
|
33
50
|
if (params.skip) {
|
|
34
51
|
continue;
|
|
35
52
|
}
|
|
36
53
|
|
|
54
|
+
const t_duration = t1 - t0;
|
|
55
|
+
|
|
56
|
+
console.log(`Executed ${params.label} in ${t_duration}ms`);
|
|
37
57
|
|
|
38
|
-
const view = display(engine, out, draw_index * (size.x + 4), 0);
|
|
39
58
|
|
|
40
|
-
|
|
41
|
-
|
|
59
|
+
const draw_x = (draw_index % tiles_x) * (size.x + GAP_SIZE);
|
|
60
|
+
const draw_y = Math.floor(draw_index / tiles_x) * (size.y + GAP_SIZE);
|
|
61
|
+
|
|
62
|
+
const view = display(engine, out, draw_x, draw_y);
|
|
63
|
+
|
|
64
|
+
if (params.label.length > 0 && display_labels) {
|
|
65
|
+
const vLabel = new LabelView(params.label, {
|
|
42
66
|
css: {
|
|
43
67
|
position: 'absolute',
|
|
44
68
|
fontFamily: 'sans-serif',
|
|
@@ -51,7 +75,9 @@ function grid(engine, input, transforms, size = new Vector2(input.width, input.h
|
|
|
51
75
|
background: 'rgba(255,255,255,0.7)',
|
|
52
76
|
padding: '2px'
|
|
53
77
|
}
|
|
54
|
-
})
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
view.addChild(vLabel);
|
|
55
81
|
}
|
|
56
82
|
|
|
57
83
|
draw_index++;
|
|
@@ -95,16 +121,22 @@ new EngineHarness().initialize({
|
|
|
95
121
|
}
|
|
96
122
|
}).then(async engine => {
|
|
97
123
|
|
|
98
|
-
// const
|
|
99
|
-
// const
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
// const
|
|
103
|
-
// const
|
|
104
|
-
// const
|
|
105
|
-
// const
|
|
106
|
-
// const
|
|
107
|
-
// const
|
|
124
|
+
// const path = "data/textures/utility/image018.jpg";
|
|
125
|
+
// const path = "data/textures/decal/ISO 7010 - Safety Signs/Fire Protection/200px/F001 – Fire extinguisher.png";
|
|
126
|
+
// const path = "data/textures/decal/ISO 7010 - Safety Signs/Prohibited Actions/400px/P069 - Not to be serviced by users.png";
|
|
127
|
+
const path = "data/textures/utility/Lenna.png";
|
|
128
|
+
// const path = "data/textures/utility/dragon.jpg";
|
|
129
|
+
// const path = "data/textures/utility/grid_tileable.png";
|
|
130
|
+
// const path = "data/textures/utility/uv_map_reference.jpg";
|
|
131
|
+
// const path ="data/textures/utility/TESTIMAGES/SAMPLING/8BIT/RGB/2448x2448/SRC/img_2448x2448_3x8bit_SRC_RGB_clips.png";
|
|
132
|
+
// const path ="data/textures/utility/TESTIMAGES/SAMPLING/8BIT/RGB/2448x2448/SRC/img_2448x2448_3x8bit_SRC_RGB_coins.png";
|
|
133
|
+
// const path ="data/models/LowPolyTownshipSet/Small_house/diffuse_512.png";
|
|
134
|
+
// const path ="data/models/LowPolyTownshipSet/Barrel/diffuse_256.png";
|
|
135
|
+
// const path ="data/textures/utility/resolver.jpeg";
|
|
136
|
+
// const path ="data/textures/icons/500_skill_icons_02/Skill_nobg/skill_492_noBG.png";
|
|
137
|
+
// const path = "data/textures/utility/sampling-test.png";
|
|
138
|
+
|
|
139
|
+
const asset = await engine.assetManager.promise(path, 'image');
|
|
108
140
|
|
|
109
141
|
const source = asset.create();
|
|
110
142
|
|
|
@@ -144,109 +176,178 @@ new EngineHarness().initialize({
|
|
|
144
176
|
})
|
|
145
177
|
|
|
146
178
|
function test_sampling(source, engine) {
|
|
147
|
-
grid(
|
|
148
|
-
|
|
149
|
-
|
|
179
|
+
grid({
|
|
180
|
+
engine: engine,
|
|
181
|
+
input: source,
|
|
182
|
+
// display_labels: false,
|
|
183
|
+
transforms: [
|
|
184
|
+
(out, input, params) => {
|
|
185
|
+
params.label = 'Nearest';
|
|
150
186
|
|
|
151
|
-
|
|
152
|
-
|
|
187
|
+
const sample = [];
|
|
188
|
+
for (let y = 0; y < out.height; y++) {
|
|
153
189
|
|
|
154
|
-
|
|
190
|
+
for (let x = 0; x < out.width; x++) {
|
|
155
191
|
|
|
156
|
-
|
|
192
|
+
input.sampleNearestUV(x / (out.width - 1), y / (out.height - 1), sample);
|
|
157
193
|
|
|
158
|
-
|
|
194
|
+
out.set(x, y, sample);
|
|
195
|
+
}
|
|
159
196
|
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
(out, input, params) => {
|
|
197
|
+
},
|
|
198
|
+
(out, input, params) => {
|
|
163
199
|
|
|
164
|
-
|
|
165
|
-
|
|
200
|
+
params.label = 'Bilinear';
|
|
201
|
+
params.skip = true;
|
|
166
202
|
|
|
167
|
-
|
|
168
|
-
for (let y = 0; y < out.height; y++) {
|
|
203
|
+
return;
|
|
169
204
|
|
|
170
|
-
|
|
205
|
+
const sample = new Uint8ClampedArray(4);
|
|
206
|
+
for (let y = 0; y < out.height; y++) {
|
|
171
207
|
|
|
172
|
-
|
|
208
|
+
for (let x = 0; x < out.width; x++) {
|
|
173
209
|
|
|
174
|
-
|
|
210
|
+
input.sampleBilinearUV(x / (out.width - 1), y / (out.height - 1), sample);
|
|
211
|
+
|
|
212
|
+
out.set(x, y, sample);
|
|
213
|
+
}
|
|
175
214
|
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
215
|
+
},
|
|
216
|
+
(out, input, params) => {
|
|
217
|
+
params.label = 'Bicubic';
|
|
218
|
+
params.skip = true;
|
|
219
|
+
|
|
220
|
+
return;
|
|
181
221
|
|
|
182
|
-
|
|
183
|
-
|
|
222
|
+
const sample = new Uint8ClampedArray(4);
|
|
223
|
+
for (let y = 0; y < out.height; y++) {
|
|
184
224
|
|
|
185
|
-
|
|
225
|
+
for (let x = 0; x < out.width; x++) {
|
|
186
226
|
|
|
187
|
-
|
|
227
|
+
input.sampleBicubicUV(x / (out.width - 1), y / (out.height - 1), sample);
|
|
188
228
|
|
|
189
|
-
|
|
229
|
+
out.set(x, y, sample);
|
|
230
|
+
}
|
|
190
231
|
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
232
|
+
},
|
|
233
|
+
(out, input, params) => {
|
|
234
|
+
params.label = 'catmull-rom';
|
|
235
|
+
params.skip = true;
|
|
236
|
+
|
|
237
|
+
return;
|
|
196
238
|
|
|
197
|
-
|
|
198
|
-
|
|
239
|
+
const sample = new Uint8ClampedArray(4);
|
|
240
|
+
for (let y = 0; y < out.height; y++) {
|
|
199
241
|
|
|
200
|
-
|
|
242
|
+
for (let x = 0; x < out.width; x++) {
|
|
201
243
|
|
|
202
|
-
|
|
244
|
+
input.sampleCatmullRomUV(x / (out.width - 1), y / (out.height - 1), sample);
|
|
203
245
|
|
|
204
|
-
|
|
246
|
+
out.set(x, y, sample);
|
|
247
|
+
}
|
|
205
248
|
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
params.label = 'mip';
|
|
249
|
+
},
|
|
250
|
+
(out, input, params) => {
|
|
251
|
+
params.label = 'mip';
|
|
210
252
|
|
|
211
253
|
|
|
212
|
-
|
|
254
|
+
sampler2d_downsample_mipmap(input, out);
|
|
213
255
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
256
|
+
},
|
|
257
|
+
(out, input, params) => {
|
|
258
|
+
const lobes = 2;
|
|
259
|
+
params.label = `lanczos_${lobes}`;
|
|
260
|
+
// params.skip = true;
|
|
219
261
|
|
|
220
|
-
|
|
262
|
+
// return;
|
|
221
263
|
|
|
222
|
-
|
|
264
|
+
sampler2D_scale_down_lanczos(input, out, lobes);
|
|
223
265
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
266
|
+
},
|
|
267
|
+
(out, input, params) => {
|
|
268
|
+
const lobes = 3;
|
|
269
|
+
params.label = `lanczos_${lobes}`;
|
|
270
|
+
params.skip = true;
|
|
228
271
|
|
|
272
|
+
return;
|
|
229
273
|
|
|
230
|
-
sampler2D_scale_down_lanczos(input, out, lobes);
|
|
231
274
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
const lobes = 5;
|
|
235
|
-
params.skip = true;
|
|
236
|
-
params.label = `lanczos_${lobes}`;
|
|
275
|
+
sampler2d_scale_down_generic(input, out, filter_lanczos3, 3);
|
|
276
|
+
// sampler2D_scale_down_lanczos(input, out, lobes);
|
|
237
277
|
|
|
238
|
-
|
|
278
|
+
},
|
|
279
|
+
(out, input, params) => {
|
|
280
|
+
const lobes = 5;
|
|
281
|
+
params.label = `lanczos_${lobes}`;
|
|
282
|
+
params.skip = true;
|
|
239
283
|
|
|
240
|
-
|
|
284
|
+
return;
|
|
241
285
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
286
|
+
sampler2D_scale_down_lanczos(input, out, lobes);
|
|
287
|
+
|
|
288
|
+
},
|
|
289
|
+
(out, input, params) => {
|
|
290
|
+
params.label = `mitchell`;
|
|
291
|
+
// params.skip = true;
|
|
249
292
|
|
|
250
|
-
|
|
293
|
+
// return;
|
|
251
294
|
|
|
295
|
+
sampler2d_scale_down_generic(input, out, mitchell_v1);
|
|
296
|
+
|
|
297
|
+
},
|
|
298
|
+
(out, input, params) => {
|
|
299
|
+
params.label = `kaiser_3`;
|
|
300
|
+
// params.skip = true;
|
|
301
|
+
|
|
302
|
+
// return;
|
|
303
|
+
|
|
304
|
+
sampler2d_scale_down_generic(input, out, kaiser_bessel_window);
|
|
305
|
+
|
|
306
|
+
},
|
|
307
|
+
(out, input, params) => {
|
|
308
|
+
params.label = `kaiser_1`;
|
|
309
|
+
// params.skip = true;
|
|
310
|
+
|
|
311
|
+
// return;
|
|
312
|
+
|
|
313
|
+
sampler2d_scale_down_generic(input, out, kaiser_1);
|
|
314
|
+
|
|
315
|
+
},
|
|
316
|
+
(out, input, params) => {
|
|
317
|
+
params.label = `triangle`;
|
|
318
|
+
// params.skip = true;
|
|
319
|
+
|
|
320
|
+
// return;
|
|
321
|
+
|
|
322
|
+
sampler2d_scale_down_generic(input, out, triangle);
|
|
323
|
+
|
|
324
|
+
},
|
|
325
|
+
(out, input, params) => {
|
|
326
|
+
params.label = `box`;
|
|
327
|
+
// params.skip = true;
|
|
328
|
+
|
|
329
|
+
// return;
|
|
330
|
+
|
|
331
|
+
sampler2d_scale_down_generic(input, out, box);
|
|
332
|
+
|
|
333
|
+
},
|
|
334
|
+
(out, input, params) => {
|
|
335
|
+
params.label = `gaussian`;
|
|
336
|
+
// params.skip = true;
|
|
337
|
+
|
|
338
|
+
// return;
|
|
339
|
+
|
|
340
|
+
sampler2d_scale_down_generic(input, out, gaussian);
|
|
341
|
+
|
|
342
|
+
}
|
|
343
|
+
], size: new Vector2(
|
|
344
|
+
// 100, 100
|
|
345
|
+
// 1024, 1024
|
|
346
|
+
136, 136
|
|
347
|
+
// 64, 64
|
|
348
|
+
// 32,32
|
|
349
|
+
// 400,400
|
|
350
|
+
// 200, 200
|
|
351
|
+
)
|
|
352
|
+
});
|
|
252
353
|
}
|
|
@@ -23,23 +23,63 @@ function lanczos(x, lobes) {
|
|
|
23
23
|
return 0;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
if (x <
|
|
26
|
+
if (x < 1.1920929e-7) {
|
|
27
27
|
return 1;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
x *= Math.PI;
|
|
31
|
+
|
|
30
32
|
const xx = x / lobes;
|
|
31
33
|
|
|
32
|
-
return Math.sin(
|
|
34
|
+
return (Math.sin(x) / x) * Math.sin(xx) / (xx);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Original formulation version from wiki
|
|
39
|
+
* @see https://en.wikipedia.org/wiki/Lanczos_resampling
|
|
40
|
+
* Calculate lanczos weight
|
|
41
|
+
* @param {number} x
|
|
42
|
+
* @param {number} lobes
|
|
43
|
+
* @returns {number}
|
|
44
|
+
*/
|
|
45
|
+
function lanczos_orig(x, lobes) {
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
// not needed in our case, as X is always positive
|
|
49
|
+
if (x < 0) {
|
|
50
|
+
x = -x;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
if (x > lobes) {
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (x < 1.1920929e-7) {
|
|
60
|
+
return 1;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return (lobes * Math.sin(Math.PI * x) * Math.sin(Math.PI * x / lobes)) / (Math.PI * Math.PI * x * x);
|
|
33
64
|
}
|
|
34
65
|
|
|
35
|
-
export function filter_lanczos3(
|
|
36
|
-
|
|
37
|
-
|
|
66
|
+
export function filter_lanczos3(x) {
|
|
67
|
+
// assume the input is positive
|
|
68
|
+
|
|
69
|
+
// if (x < 0) {
|
|
70
|
+
// x = -x;
|
|
71
|
+
// }
|
|
72
|
+
|
|
73
|
+
if (x > 3) {
|
|
74
|
+
return 0;
|
|
38
75
|
}
|
|
39
|
-
|
|
40
|
-
|
|
76
|
+
|
|
77
|
+
if (x < 1.1920929e-7) {
|
|
78
|
+
return 1;
|
|
41
79
|
}
|
|
42
|
-
|
|
80
|
+
|
|
81
|
+
return (3 * Math.sin(Math.PI * x) * Math.sin(Math.PI * x / 3)) / (Math.PI * Math.PI * x * x);
|
|
82
|
+
|
|
43
83
|
}
|
|
44
84
|
|
|
45
85
|
filter_lanczos3.support = 3;
|
|
@@ -51,7 +91,7 @@ filter_lanczos3.support = 3;
|
|
|
51
91
|
* @param {Sampler2D} destination
|
|
52
92
|
* @param {number} [lobes]
|
|
53
93
|
*/
|
|
54
|
-
export function sampler2D_scale_down_lanczos(source, destination, lobes =
|
|
94
|
+
export function sampler2D_scale_down_lanczos(source, destination, lobes = 2) {
|
|
55
95
|
|
|
56
96
|
const d_w = destination.width;
|
|
57
97
|
const d_h = destination.height;
|
|
@@ -61,15 +101,22 @@ export function sampler2D_scale_down_lanczos(source, destination, lobes = 3) {
|
|
|
61
101
|
const source_width = source.width;
|
|
62
102
|
const source_height = source.height;
|
|
63
103
|
|
|
104
|
+
if (source_width < d_w || source_height < d_h) {
|
|
105
|
+
throw new Error('Invalid scale, source is larger than destination in at least 1 dimension');
|
|
106
|
+
}
|
|
107
|
+
|
|
64
108
|
const source_data = source.data;
|
|
65
109
|
const destination_data = destination.data;
|
|
66
110
|
|
|
67
111
|
const ratio_x = source_width / d_w;
|
|
68
112
|
const ratio_y = source_height / d_h;
|
|
69
113
|
|
|
114
|
+
const rcp_ratio_y = 2 / ratio_x;
|
|
115
|
+
const rcp_ratio_x = 2 / ratio_x;
|
|
116
|
+
|
|
70
117
|
|
|
71
|
-
const range2_x = Math.ceil(ratio_x * lobes
|
|
72
|
-
const range2_y = Math.ceil(ratio_y * lobes
|
|
118
|
+
const range2_x = Math.ceil(ratio_x * lobes * 0.5);
|
|
119
|
+
const range2_y = Math.ceil(ratio_y * lobes * 0.5);
|
|
73
120
|
|
|
74
121
|
const sample = new Array(item_size);
|
|
75
122
|
|
|
@@ -77,17 +124,20 @@ export function sampler2D_scale_down_lanczos(source, destination, lobes = 3) {
|
|
|
77
124
|
|
|
78
125
|
for (v = 0; v < d_h; v++) {
|
|
79
126
|
|
|
80
|
-
const center_y = (v) * ratio_y
|
|
81
|
-
const
|
|
82
|
-
|
|
127
|
+
const center_y = (v + 0.5) * ratio_y;
|
|
128
|
+
const i_center_y = Math.floor(center_y);
|
|
129
|
+
//
|
|
130
|
+
const source_y0 = max2(0, i_center_y - range2_y);
|
|
131
|
+
const source_y1 = min2(i_center_y + range2_y, source_height - 1);
|
|
83
132
|
|
|
84
133
|
for (u = 0; u < d_w; u++) {
|
|
85
|
-
const center_x = (u) * ratio_x
|
|
134
|
+
const center_x = (u + 0.5) * ratio_x;
|
|
135
|
+
const i_center_x = Math.floor(center_x);
|
|
86
136
|
|
|
87
|
-
const source_x0 = max2(
|
|
88
|
-
const source_x1 = min2(
|
|
137
|
+
const source_x0 = max2(i_center_x - range2_x, 0);
|
|
138
|
+
const source_x1 = min2(i_center_x + range2_x, source_width - 1);
|
|
89
139
|
|
|
90
|
-
let
|
|
140
|
+
let weight_sum = 0;
|
|
91
141
|
// reset sample
|
|
92
142
|
for (i = 0; i < item_size; i++) {
|
|
93
143
|
sample[i] = 0;
|
|
@@ -97,29 +147,31 @@ export function sampler2D_scale_down_lanczos(source, destination, lobes = 3) {
|
|
|
97
147
|
|
|
98
148
|
const f_y = (j - center_y);
|
|
99
149
|
|
|
100
|
-
const
|
|
150
|
+
const f_y_rcp = f_y * rcp_ratio_y;
|
|
151
|
+
const f_y_rcp2 = f_y_rcp * f_y_rcp;
|
|
101
152
|
|
|
102
153
|
for (i = source_x0; i <= source_x1; i++) {
|
|
103
154
|
|
|
104
155
|
const f_x = (i - center_x);
|
|
105
156
|
|
|
106
|
-
const
|
|
157
|
+
const f_x_rcp = f_x * rcp_ratio_x;
|
|
158
|
+
const f_x_rcp2 = f_x_rcp * f_x_rcp;
|
|
107
159
|
|
|
108
160
|
const distance_from_center_sqr = f_x_rcp2 + f_y_rcp2;
|
|
109
161
|
const distance_from_center = Math.sqrt(distance_from_center_sqr);
|
|
110
162
|
|
|
111
|
-
const
|
|
163
|
+
const weight = lanczos(distance_from_center, lobes);
|
|
112
164
|
|
|
113
|
-
if (
|
|
165
|
+
if (weight <= 0) {
|
|
114
166
|
continue;
|
|
115
167
|
}
|
|
116
168
|
|
|
117
|
-
|
|
169
|
+
weight_sum += weight;
|
|
118
170
|
|
|
119
171
|
const source_texel_address = (j * source_width + i) * item_size;
|
|
120
172
|
|
|
121
173
|
for (k = 0; k < item_size; k++) {
|
|
122
|
-
sample[k] +=
|
|
174
|
+
sample[k] += weight * source_data[source_texel_address + k];
|
|
123
175
|
}
|
|
124
176
|
|
|
125
177
|
}
|
|
@@ -127,7 +179,7 @@ export function sampler2D_scale_down_lanczos(source, destination, lobes = 3) {
|
|
|
127
179
|
|
|
128
180
|
|
|
129
181
|
// dilute sample and write to destination
|
|
130
|
-
const inv_z = 1 /
|
|
182
|
+
const inv_z = 1 / weight_sum;
|
|
131
183
|
|
|
132
184
|
const texel_address = (v * d_w + u) * item_size;
|
|
133
185
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge detection condition generator
|
|
3
|
+
* @param {number} channel
|
|
4
|
+
* @param {number} threshold
|
|
5
|
+
* @returns {(sampler:Sampler2D, x:number, y:number) => boolean}
|
|
6
|
+
*/
|
|
7
|
+
export function make_edge_condition_channel_threshold(channel, threshold) {
|
|
8
|
+
/**
|
|
9
|
+
* @param {Sampler2D} sampler
|
|
10
|
+
* @param {number} x
|
|
11
|
+
* @param {number} y
|
|
12
|
+
* @returns {boolean}
|
|
13
|
+
*/
|
|
14
|
+
return function (sampler, x, y) {
|
|
15
|
+
const v = sampler.readChannel(x, y, channel);
|
|
16
|
+
|
|
17
|
+
if (v < threshold) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (
|
|
22
|
+
(y > 0 && sampler.readChannel(x, y - 1, channel) < threshold) // up
|
|
23
|
+
|| (x > 0 && sampler.readChannel(x - 1, y, channel) < threshold) //left
|
|
24
|
+
|| (x < (sampler.width - 1) && sampler.readChannel(x + 1, y, channel) < threshold) //right
|
|
25
|
+
|| (y < (sampler.height - 1) && sampler.readChannel(x, y + 1, channel) < threshold) //bottom
|
|
26
|
+
) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
// not edge, probably interior
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {Sampler2D} sampler
|
|
4
|
+
* @param {(sampler:Sampler2D,x:number, y:number)=>boolean} matcher
|
|
5
|
+
* @returns {number[]} flat array of x,y coordinates
|
|
6
|
+
*/
|
|
7
|
+
export function sampler2d_find_pixels(sampler, matcher) {
|
|
8
|
+
const result = [];
|
|
9
|
+
|
|
10
|
+
const h = sampler.height;
|
|
11
|
+
const w = sampler.width;
|
|
12
|
+
|
|
13
|
+
for (let y = 0; y < h; y++) {
|
|
14
|
+
for (let x = 0; x < w; x++) {
|
|
15
|
+
|
|
16
|
+
if (matcher(sampler, x, y)) {
|
|
17
|
+
result.push(x, y);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return result;
|
|
24
|
+
}
|