@woosh/meep-engine 2.39.39 → 2.39.42
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/operations/ceilPowerOfTwo.spec.js +17 -0
- package/core/bvh2/aabb3/AABB3.js +6 -6
- package/core/bvh2/binary/2/BinaryUint32BVH.js +7 -1
- package/core/bvh2/binary/2/BinaryUint32BVH.spec.js +31 -1
- package/core/bvh2/bvh3/bvh_query_user_data_nearest_to_point.js +5 -5
- package/core/bvh2/bvh3/bvh_query_user_data_nearest_to_point.spec.js +70 -0
- package/core/bvh2/bvh3/query/compute_tight_near_far_clipping_planes.spec.js +2 -2
- package/core/cache/Cache.js +6 -0
- package/core/collection/IteratorUtils.js +1 -0
- package/core/collection/queue/Deque.js +5 -2
- package/core/color/Color.js +22 -4
- package/core/color/hsluv/HSLuv.js +187 -0
- package/core/geom/3d/aabb/aabb3_matrix4_project.js +1 -0
- package/core/geom/3d/topology/simplify/simplifyTopoMesh2.js +1 -1
- package/core/primitives/strings/compareStrings.js +22 -0
- package/editor/Editor.js +2 -0
- package/editor/ecs/component/editors/ecs/terrain/TerrainEditor.js +12 -6
- package/editor/tools/v2/BlenderCameraOrientationGizmo.js +22 -11
- package/engine/EngineHarness.js +7 -0
- package/engine/asset/loaders/geometry/geometry/computeBufferAttributeHash.js +5 -6
- package/engine/asset/loaders/image/codec/Codec.js +9 -0
- package/engine/asset/loaders/image/codec/CodecWithFallback.js +52 -11
- package/engine/asset/loaders/image/codec/ThreadedImageDecoder.js +12 -0
- package/engine/asset/loaders/image/png/PNGReader.js +2 -1
- package/engine/asset/loaders/image/png/PNG_HEADER_BYTES.js +1 -0
- package/engine/computeStridedIntegerArrayHash.js +19 -0
- package/engine/ecs/EntityBuilder.d.ts +2 -0
- package/engine/ecs/gui/GUIElement.d.ts +3 -1
- package/engine/ecs/terrain/ecs/layers/TerrainLayers.js +5 -3
- package/engine/graphics/ecs/light/binding/fp/FPLightBinding.js +11 -2
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +2 -8
- package/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.d.ts +7 -0
- package/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +17 -1
- package/engine/graphics/geometry/optimization/merge/merge_geometry_hierarchy.js +336 -0
- package/engine/graphics/geometry/optimization/merge/prototypeGeometryMerge.js +176 -0
- package/engine/graphics/micron/build/hierarchy/buildAbstractPatchHierarchy.js +7 -3
- package/engine/graphics/micron/build/hierarchy/merge_patches.js +0 -1
- package/engine/graphics/micron/prototypeVirtualGeometry.js +3 -3
- package/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +32 -1
- package/engine/graphics/render/forward_plus/LightManager.js +58 -13
- package/engine/graphics/render/forward_plus/debug/createScreenGrid.js +192 -9
- package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +42 -1
- package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_PREAMBLE.js +1 -0
- package/engine/graphics/render/forward_plus/materials/ForwardPlusThreeMaterial.js +5 -0
- package/engine/graphics/render/forward_plus/materials/fp_build_fragment_shader.js +1 -4
- package/engine/graphics/render/forward_plus/model/Decal.js +33 -5
- package/engine/graphics/render/forward_plus/model/PointLight.js +1 -1
- package/engine/graphics/render/forward_plus/plugin/MaterialTransformer.js +4 -0
- package/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +480 -12
- package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +49 -29
- package/engine/graphics/texture/atlas/AbstractTextureAtlas.js +11 -0
- package/engine/graphics/texture/atlas/CachingTextureAtlas.js +34 -0
- package/engine/graphics/texture/atlas/ReferencedTextureAtlas.js +9 -1
- package/engine/graphics/texture/atlas/TextureAtlas.js +29 -16
- package/engine/graphics/texture/atlas/TextureAtlasDebugger.js +75 -19
- package/engine/graphics/texture/sampler/Sampler2D.d.ts +2 -0
- package/engine/graphics/texture/sampler/Sampler2D.js +51 -10
- package/engine/sound/ecs/SoundListenerSystem.js +5 -0
- package/engine/sound/ecs/emitter/SoundEmitter.js +12 -1
- package/package.json +1 -1
- package/samples/terrain/from_image_2.js +8 -2
- package/view/tooltip/TooltipManager.js +0 -95
|
@@ -10,6 +10,48 @@ import { BVH_BINARY_NODE_SIZE, BVH_LEAF_NODE_SIZE } from "../../../../../core/bv
|
|
|
10
10
|
*/
|
|
11
11
|
const stack = [];
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @param {DataView} data_view
|
|
16
|
+
* @param {number} address
|
|
17
|
+
* @param {ArrayLike<number>|number[]} planes
|
|
18
|
+
* @return {boolean}
|
|
19
|
+
*/
|
|
20
|
+
function frustum_check(data_view, address, planes) {
|
|
21
|
+
const n_x0 = data_view.getFloat32(address);
|
|
22
|
+
const n_y0 = data_view.getFloat32(address + 4);
|
|
23
|
+
const n_z0 = data_view.getFloat32(address + 8);
|
|
24
|
+
const n_x1 = data_view.getFloat32(address + 12);
|
|
25
|
+
const n_y1 = data_view.getFloat32(address + 16);
|
|
26
|
+
const n_z1 = data_view.getFloat32(address + 20);
|
|
27
|
+
|
|
28
|
+
for (let plane_address = 0; plane_address < 24; plane_address += 4) {
|
|
29
|
+
|
|
30
|
+
const plane_normal_x = planes[plane_address];
|
|
31
|
+
const plane_normal_y = planes[plane_address + 1];
|
|
32
|
+
const plane_normal_z = planes[plane_address + 2];
|
|
33
|
+
const plane_constant = planes[plane_address + 3];
|
|
34
|
+
|
|
35
|
+
const distanceAbovePlane = aabb3_computeDistanceAbovePlane_max(
|
|
36
|
+
plane_normal_x, plane_normal_y, plane_normal_z, plane_constant,
|
|
37
|
+
n_x0, n_y0, n_z0,
|
|
38
|
+
n_x1, n_y1, n_z1
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
if (distanceAbovePlane <= 0) {
|
|
42
|
+
// node is below the plane
|
|
43
|
+
|
|
44
|
+
// query_bvh_frustum_from_objects.rejection_count++;
|
|
45
|
+
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// TODO under current scheme we can reserve 6 bit in what we push onto the stack for plane mask (allows us to skip some planar tests)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
13
55
|
/**
|
|
14
56
|
* Most of the data is in flat continuous array for cache coherence
|
|
15
57
|
* @param {number[]} destination
|
|
@@ -57,35 +99,8 @@ export function query_bvh_frustum_from_texture(
|
|
|
57
99
|
// is intermediate node
|
|
58
100
|
const node_address = node_index * BVH_BINARY_NODE_SIZE;
|
|
59
101
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const n_z0 = data_view.getFloat32(node_address + 8);
|
|
63
|
-
const n_x1 = data_view.getFloat32(node_address + 12);
|
|
64
|
-
const n_y1 = data_view.getFloat32(node_address + 16);
|
|
65
|
-
const n_z1 = data_view.getFloat32(node_address + 20);
|
|
66
|
-
|
|
67
|
-
for (plane_address = 0; plane_address < 24; plane_address += 4) {
|
|
68
|
-
|
|
69
|
-
const plane_normal_x = planes[plane_address];
|
|
70
|
-
const plane_normal_y = planes[plane_address + 1];
|
|
71
|
-
const plane_normal_z = planes[plane_address + 2];
|
|
72
|
-
const plane_constant = planes[plane_address + 3];
|
|
73
|
-
|
|
74
|
-
const distanceAbovePlane = aabb3_computeDistanceAbovePlane_max(
|
|
75
|
-
plane_normal_x, plane_normal_y, plane_normal_z, plane_constant,
|
|
76
|
-
n_x0, n_y0, n_z0,
|
|
77
|
-
n_x1, n_y1, n_z1
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
if (distanceAbovePlane < 0) {
|
|
81
|
-
// node is below the plane
|
|
82
|
-
|
|
83
|
-
// query_bvh_frustum_from_objects.rejection_count++;
|
|
84
|
-
|
|
85
|
-
continue stack_loop;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// TODO under current scheme we can reserve 6 bit in what we push onto the stack for plane mask (allows us to skip some planar tests)
|
|
102
|
+
if (!frustum_check(data_view, node_address, planes)) {
|
|
103
|
+
continue;
|
|
89
104
|
}
|
|
90
105
|
|
|
91
106
|
const left_index = (node_index << 1) + 1;
|
|
@@ -130,6 +145,11 @@ export function query_bvh_frustum_from_texture(
|
|
|
130
145
|
|
|
131
146
|
} else if (light_type === 3) {
|
|
132
147
|
// decal
|
|
148
|
+
|
|
149
|
+
if (!frustum_check(data_view, node_address, planes)) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
|
|
133
153
|
} else {
|
|
134
154
|
throw new Error(`Unsupported light type ${light_type}`);
|
|
135
155
|
}
|
|
@@ -16,4 +16,15 @@ export class AbstractTextureAtlas {
|
|
|
16
16
|
remove(patch) {
|
|
17
17
|
throw new Error('Not Implemented')
|
|
18
18
|
}
|
|
19
|
+
|
|
20
|
+
get sampler() {
|
|
21
|
+
throw new Error('Not Implemented')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @throws {Error} if update fails
|
|
26
|
+
*/
|
|
27
|
+
update() {
|
|
28
|
+
throw new Error('Not Implemented')
|
|
29
|
+
}
|
|
19
30
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Cache } from "../../../../core/cache/Cache.js";
|
|
2
2
|
import { AbstractTextureAtlas } from "./AbstractTextureAtlas.js";
|
|
3
|
+
import { invokeObjectHash } from "../../../../core/model/object/invokeObjectHash.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* 4Mb
|
|
@@ -26,6 +27,7 @@ export class CachingTextureAtlas extends AbstractTextureAtlas {
|
|
|
26
27
|
*/
|
|
27
28
|
this.__cached_patches = new Cache({
|
|
28
29
|
maxWeight: cache_size,
|
|
30
|
+
keyHashFunction: invokeObjectHash,
|
|
29
31
|
keyWeigher(sampler) {
|
|
30
32
|
return sampler.computeByteSize();
|
|
31
33
|
}
|
|
@@ -41,6 +43,25 @@ export class CachingTextureAtlas extends AbstractTextureAtlas {
|
|
|
41
43
|
this.__cached_patches.onEvicted.add(this.__handle_cache_eviction, this);
|
|
42
44
|
}
|
|
43
45
|
|
|
46
|
+
update() {
|
|
47
|
+
try {
|
|
48
|
+
this.__atals.update();
|
|
49
|
+
} catch (e) {
|
|
50
|
+
if (this.__cached_patches.size() > 0) {
|
|
51
|
+
|
|
52
|
+
// has some caches patches, lets drop them
|
|
53
|
+
this.__cached_patches.clear();
|
|
54
|
+
|
|
55
|
+
// try to update again
|
|
56
|
+
this.__atals.update();
|
|
57
|
+
|
|
58
|
+
} else {
|
|
59
|
+
// just re-throw
|
|
60
|
+
throw e;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
44
65
|
/**
|
|
45
66
|
*
|
|
46
67
|
* @returns {AbstractTextureAtlas}
|
|
@@ -49,6 +70,14 @@ export class CachingTextureAtlas extends AbstractTextureAtlas {
|
|
|
49
70
|
return this.__atals;
|
|
50
71
|
}
|
|
51
72
|
|
|
73
|
+
/**
|
|
74
|
+
*
|
|
75
|
+
* @return {Sampler2D}
|
|
76
|
+
*/
|
|
77
|
+
get sampler() {
|
|
78
|
+
return this.__atals.sampler;
|
|
79
|
+
}
|
|
80
|
+
|
|
52
81
|
/**
|
|
53
82
|
*
|
|
54
83
|
* @param {Sampler2D} sampler
|
|
@@ -74,6 +103,11 @@ export class CachingTextureAtlas extends AbstractTextureAtlas {
|
|
|
74
103
|
|
|
75
104
|
if (existing_patch !== null) {
|
|
76
105
|
// cache hit
|
|
106
|
+
|
|
107
|
+
// remove from cache
|
|
108
|
+
this.__cached_patches.remove(sampler);
|
|
109
|
+
|
|
110
|
+
// return patch
|
|
77
111
|
return existing_patch;
|
|
78
112
|
}
|
|
79
113
|
|
|
@@ -26,6 +26,10 @@ export class ReferencedTextureAtlas extends AbstractTextureAtlas {
|
|
|
26
26
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
update() {
|
|
30
|
+
this.__atlas.update();
|
|
31
|
+
}
|
|
32
|
+
|
|
29
33
|
/**
|
|
30
34
|
*
|
|
31
35
|
* @param {Reference} ref
|
|
@@ -39,8 +43,10 @@ export class ReferencedTextureAtlas extends AbstractTextureAtlas {
|
|
|
39
43
|
ref_counts.set(patch, ref_count - 1);
|
|
40
44
|
|
|
41
45
|
if (ref_count === 1) {
|
|
42
|
-
// clear patch
|
|
46
|
+
// last reference removed, clear patch
|
|
43
47
|
this.__atlas.remove(patch);
|
|
48
|
+
ref_counts.delete(patch);
|
|
49
|
+
this.__patches.delete(patch.sampler);
|
|
44
50
|
}
|
|
45
51
|
}
|
|
46
52
|
|
|
@@ -61,6 +67,8 @@ export class ReferencedTextureAtlas extends AbstractTextureAtlas {
|
|
|
61
67
|
if (patch === undefined) {
|
|
62
68
|
patch = atlas.add(sampler);
|
|
63
69
|
ref_counts.set(patch, 1)
|
|
70
|
+
|
|
71
|
+
this.__patches.set(sampler, patch);
|
|
64
72
|
} else {
|
|
65
73
|
ref_counts.set(patch, ref_counts.get(patch) + 1);
|
|
66
74
|
}
|
|
@@ -9,7 +9,9 @@ import { AtlasPatchFlag } from "./AtlasPatchFlag.js";
|
|
|
9
9
|
import Signal from "../../../../core/events/signal/Signal.js";
|
|
10
10
|
import { assert } from "../../../../core/assert.js";
|
|
11
11
|
import { DataType } from "../../../../core/collection/table/DataType.js";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
DataType2TypedArrayConstructorMapping
|
|
14
|
+
} from "../../../../core/collection/table/DataType2TypedArrayConstructorMapping.js";
|
|
13
15
|
import { AbstractTextureAtlas } from "./AbstractTextureAtlas.js";
|
|
14
16
|
import { invokeObjectClone } from "../../../../core/model/object/invokeObjectClone.js";
|
|
15
17
|
|
|
@@ -47,10 +49,11 @@ export class TextureAtlas extends AbstractTextureAtlas {
|
|
|
47
49
|
const channel_count = 4;
|
|
48
50
|
|
|
49
51
|
/**
|
|
52
|
+
* @private
|
|
50
53
|
* @readonly
|
|
51
54
|
* @type {Sampler2D}
|
|
52
55
|
*/
|
|
53
|
-
this.
|
|
56
|
+
this.__sampler = new Sampler2D(new TypeArrayConstructor(size * size * channel_count), channel_count, size, size);
|
|
54
57
|
|
|
55
58
|
|
|
56
59
|
/**
|
|
@@ -71,6 +74,14 @@ export class TextureAtlas extends AbstractTextureAtlas {
|
|
|
71
74
|
this.__needsUpdate = false;
|
|
72
75
|
}
|
|
73
76
|
|
|
77
|
+
/**
|
|
78
|
+
*
|
|
79
|
+
* @return {Sampler2D}
|
|
80
|
+
*/
|
|
81
|
+
get sampler() {
|
|
82
|
+
return this.__sampler;
|
|
83
|
+
}
|
|
84
|
+
|
|
74
85
|
/**
|
|
75
86
|
*
|
|
76
87
|
* @param {Sampler2D} sampler
|
|
@@ -127,7 +138,7 @@ export class TextureAtlas extends AbstractTextureAtlas {
|
|
|
127
138
|
|
|
128
139
|
|
|
129
140
|
//erase data
|
|
130
|
-
this.
|
|
141
|
+
this.__sampler.data.fill(0);
|
|
131
142
|
|
|
132
143
|
this.__needsUpdate = true;
|
|
133
144
|
}
|
|
@@ -175,7 +186,7 @@ export class TextureAtlas extends AbstractTextureAtlas {
|
|
|
175
186
|
|
|
176
187
|
this.size.set(x, y);
|
|
177
188
|
this.packer.resize(x, y);
|
|
178
|
-
this.
|
|
189
|
+
this.__sampler.resize(x, y);
|
|
179
190
|
|
|
180
191
|
return true;
|
|
181
192
|
}
|
|
@@ -188,17 +199,17 @@ export class TextureAtlas extends AbstractTextureAtlas {
|
|
|
188
199
|
paintPatch(patch) {
|
|
189
200
|
// console.time('TextureAtlas.paintPatch');
|
|
190
201
|
|
|
191
|
-
const target = this.
|
|
202
|
+
const target = this.__sampler;
|
|
192
203
|
|
|
193
204
|
const source = patch.sampler;
|
|
194
205
|
|
|
195
|
-
const
|
|
196
|
-
const
|
|
206
|
+
const patch_position = patch.position;
|
|
207
|
+
const patch_size = patch.size;
|
|
197
208
|
|
|
198
209
|
target.copy_sameItemSize(
|
|
199
210
|
source,
|
|
200
211
|
0, 0,
|
|
201
|
-
|
|
212
|
+
patch_position.x, patch_position.y, patch_size.x, patch_size.y
|
|
202
213
|
);
|
|
203
214
|
|
|
204
215
|
patch.setFlag(AtlasPatchFlag.Painted);
|
|
@@ -222,7 +233,7 @@ export class TextureAtlas extends AbstractTextureAtlas {
|
|
|
222
233
|
|
|
223
234
|
this.eraseArea(x0, y0, x1, y1);
|
|
224
235
|
|
|
225
|
-
|
|
236
|
+
// mark as non-painted
|
|
226
237
|
patch.clearFlag(AtlasPatchFlag.Painted);
|
|
227
238
|
}
|
|
228
239
|
|
|
@@ -234,9 +245,9 @@ export class TextureAtlas extends AbstractTextureAtlas {
|
|
|
234
245
|
* @param {number} y1
|
|
235
246
|
*/
|
|
236
247
|
eraseArea(x0, y0, x1, y1) {
|
|
237
|
-
const sampler = this.
|
|
248
|
+
const sampler = this.__sampler;
|
|
238
249
|
|
|
239
|
-
sampler.zeroFill(x0, y0, x1, y1);
|
|
250
|
+
sampler.zeroFill(x0, y0, x1 - x0, y1 - y0);
|
|
240
251
|
}
|
|
241
252
|
|
|
242
253
|
/**
|
|
@@ -246,6 +257,7 @@ export class TextureAtlas extends AbstractTextureAtlas {
|
|
|
246
257
|
* @return {AtlasPatch}
|
|
247
258
|
*/
|
|
248
259
|
add(sampler, padding = 4) {
|
|
260
|
+
// console.log('#add');
|
|
249
261
|
|
|
250
262
|
const patch = new AtlasPatch();
|
|
251
263
|
|
|
@@ -272,6 +284,7 @@ export class TextureAtlas extends AbstractTextureAtlas {
|
|
|
272
284
|
* @return {boolean}
|
|
273
285
|
*/
|
|
274
286
|
remove(patch) {
|
|
287
|
+
// console.log('#remove');
|
|
275
288
|
const patchIndex = this.patches.indexOf(patch);
|
|
276
289
|
|
|
277
290
|
if (patchIndex === -1) {
|
|
@@ -282,15 +295,15 @@ export class TextureAtlas extends AbstractTextureAtlas {
|
|
|
282
295
|
this.patches.splice(patchIndex, 1);
|
|
283
296
|
this.idPool.release(patch.id);
|
|
284
297
|
|
|
285
|
-
if (patch.getFlag(AtlasPatchFlag.Packed)) {
|
|
286
|
-
this.packer.remove(patch.packing);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
298
|
if (patch.getFlag(AtlasPatchFlag.Painted)) {
|
|
290
299
|
//erase the patch
|
|
291
300
|
this.erasePatch(patch);
|
|
292
301
|
}
|
|
293
302
|
|
|
303
|
+
if (patch.getFlag(AtlasPatchFlag.Packed)) {
|
|
304
|
+
this.packer.remove(patch.packing);
|
|
305
|
+
}
|
|
306
|
+
|
|
294
307
|
return true;
|
|
295
308
|
}
|
|
296
309
|
|
|
@@ -513,7 +526,7 @@ export class TextureAtlas extends AbstractTextureAtlas {
|
|
|
513
526
|
* Drops all the data
|
|
514
527
|
*/
|
|
515
528
|
reset() {
|
|
516
|
-
this.
|
|
529
|
+
this.__sampler.data.fill(0);
|
|
517
530
|
|
|
518
531
|
this.patches = [];
|
|
519
532
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import EmptyView from "../../../../view/elements/EmptyView.js";
|
|
2
1
|
import Vector2 from "../../../../core/geom/Vector2.js";
|
|
2
|
+
import { CanvasView } from "../../../../view/elements/CanvasView.js";
|
|
3
|
+
import { FrameRunner } from "../../FrameRunner.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Visualizer for TextureAtlas, to help understand current state of the atlas
|
|
@@ -9,13 +10,19 @@ export class TextureAtlasDebugger {
|
|
|
9
10
|
*
|
|
10
11
|
* @param {TextureAtlas} atlas
|
|
11
12
|
* @param {Vector2} [scale]
|
|
13
|
+
* @param {boolean} [draw_padding]
|
|
14
|
+
* @param {boolean} [draw_borders]
|
|
12
15
|
*/
|
|
13
|
-
constructor(atlas, {
|
|
16
|
+
constructor(atlas, {
|
|
17
|
+
scale = new Vector2(1, 1),
|
|
18
|
+
draw_padding = true,
|
|
19
|
+
draw_borders = true
|
|
20
|
+
} = {}) {
|
|
14
21
|
window.atlas = atlas;
|
|
15
22
|
|
|
16
|
-
|
|
23
|
+
const vCanvas = new CanvasView();
|
|
17
24
|
|
|
18
|
-
|
|
25
|
+
vCanvas.css({
|
|
19
26
|
position: "absolute",
|
|
20
27
|
top: "0",
|
|
21
28
|
left: "0",
|
|
@@ -25,49 +32,98 @@ export class TextureAtlasDebugger {
|
|
|
25
32
|
background: 'rgba(0,0,0,0.8)'
|
|
26
33
|
});
|
|
27
34
|
|
|
28
|
-
const ctx =
|
|
35
|
+
const ctx = vCanvas.context2d;
|
|
36
|
+
|
|
37
|
+
let last_drawn_version = -1;
|
|
29
38
|
|
|
30
39
|
function draw() {
|
|
31
40
|
|
|
32
41
|
const size = atlas.size;
|
|
42
|
+
|
|
43
|
+
|
|
33
44
|
if (size.x !== 0 && size.y !== 0) {
|
|
34
45
|
ctx.clearRect(0, 0, size.x, size.y);
|
|
35
46
|
|
|
36
47
|
const imageData = ctx.createImageData(size.x, size.y);
|
|
48
|
+
|
|
37
49
|
imageData.data.set(atlas.sampler.data);
|
|
38
50
|
|
|
39
51
|
ctx.putImageData(imageData, 0, 0);
|
|
40
52
|
|
|
41
|
-
ctx.strokeStyle = 'red';
|
|
42
53
|
|
|
43
54
|
//draw patch boundaries
|
|
44
|
-
atlas.patches.
|
|
45
|
-
const
|
|
55
|
+
for (let i = 0; i < atlas.patches.length; i++) {
|
|
56
|
+
const patch = atlas.patches[i];
|
|
46
57
|
|
|
47
|
-
|
|
58
|
+
if (draw_padding) {
|
|
59
|
+
// draw padding area
|
|
60
|
+
ctx.strokeStyle = 'rgba(0,166,255,0.5)';
|
|
61
|
+
ctx.lineWidth = patch.padding;
|
|
48
62
|
|
|
49
|
-
|
|
63
|
+
ctx.strokeRect(
|
|
64
|
+
patch.position.x - patch.padding * 0.5,
|
|
65
|
+
patch.position.y - patch.padding * 0.5,
|
|
66
|
+
patch.size.x + patch.padding,
|
|
67
|
+
patch.size.y + patch.padding,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (draw_borders) {
|
|
72
|
+
const aabb2 = patch.packing;
|
|
73
|
+
|
|
74
|
+
// draw patch borders
|
|
75
|
+
ctx.strokeStyle = 'red';
|
|
76
|
+
ctx.lineWidth = 1;
|
|
77
|
+
|
|
78
|
+
ctx.strokeRect(aabb2.x0, aabb2.y0, aabb2.getWidth(), aabb2.getHeight());
|
|
79
|
+
}
|
|
80
|
+
}
|
|
50
81
|
|
|
51
82
|
} else {
|
|
52
83
|
ctx.clearRect(0, 0, 1, 1);
|
|
53
84
|
}
|
|
85
|
+
|
|
86
|
+
// remember last drawn version
|
|
87
|
+
last_drawn_version = atlas.sampler.version;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
vCanvas.size.set(0, 0);
|
|
91
|
+
|
|
92
|
+
function try_draw() {
|
|
93
|
+
if (last_drawn_version !== atlas.sampler.version) {
|
|
94
|
+
draw();
|
|
95
|
+
}
|
|
54
96
|
}
|
|
55
97
|
|
|
56
|
-
|
|
98
|
+
const write_dimensions = () => {
|
|
99
|
+
const x = atlas.size.x;
|
|
100
|
+
const y = atlas.size.y;
|
|
57
101
|
|
|
58
|
-
|
|
59
|
-
|
|
102
|
+
vCanvas.size.set(x, y);
|
|
103
|
+
vCanvas.scale.copy(scale);
|
|
104
|
+
vCanvas.transformOrigin.set(0, 0);
|
|
105
|
+
};
|
|
60
106
|
|
|
61
|
-
|
|
62
|
-
|
|
107
|
+
function full_update() {
|
|
108
|
+
write_dimensions();
|
|
109
|
+
draw();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const fr = new FrameRunner(try_draw);
|
|
63
113
|
|
|
64
|
-
|
|
65
|
-
v.el.setAttribute('width', x);
|
|
66
|
-
v.el.setAttribute('height', y);
|
|
114
|
+
atlas.size.onChanged.add(full_update);
|
|
67
115
|
|
|
116
|
+
vCanvas.on.linked.add(() => {
|
|
117
|
+
full_update();
|
|
118
|
+
fr.startup();
|
|
68
119
|
});
|
|
69
120
|
|
|
70
|
-
|
|
121
|
+
vCanvas.on.unlinked.add(() => {
|
|
122
|
+
fr.shutdown();
|
|
123
|
+
})
|
|
124
|
+
|
|
71
125
|
atlas.on.painted.add(draw);
|
|
126
|
+
|
|
127
|
+
this.vAtlasContent = vCanvas;
|
|
72
128
|
}
|
|
73
129
|
}
|
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
compute_typed_array_constructor_from_data_type
|
|
16
16
|
} from "../../../../core/collection/table/DataType2TypedArrayConstructorMapping.js";
|
|
17
17
|
import { Base64 } from "../../../../core/binary/Base64.js";
|
|
18
|
+
import { computeStridedIntegerArrayHash } from "../../../computeStridedIntegerArrayHash.js";
|
|
19
|
+
import { is_typed_array_equals } from "../../../../core/collection/array/typed/is_typed_array_equals.js";
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* @class
|
|
@@ -23,20 +25,20 @@ export class Sampler2D {
|
|
|
23
25
|
/**
|
|
24
26
|
*
|
|
25
27
|
* @param {ArrayLike<number>|number[]|Uint8ClampedArray|Uint8Array|Uint16Array|Uint32Array|Int8Array|Int16Array|Int32Array|Float32Array|Float64Array} data
|
|
26
|
-
* @param {
|
|
27
|
-
* @param {
|
|
28
|
-
* @param {
|
|
28
|
+
* @param {number} itemSize
|
|
29
|
+
* @param {number} width
|
|
30
|
+
* @param {number} height
|
|
29
31
|
* @constructor
|
|
30
32
|
*/
|
|
31
33
|
constructor(data = [], itemSize = 1, width = 0, height = 0) {
|
|
32
|
-
if (!Number.isInteger(itemSize)) {
|
|
33
|
-
throw new Error(`itemSize must be integer, instead was ${itemSize}`);
|
|
34
|
+
if (!Number.isInteger(itemSize) || itemSize < 0) {
|
|
35
|
+
throw new Error(`itemSize must be a non-negative integer, instead was ${itemSize}`);
|
|
34
36
|
}
|
|
35
|
-
if (!Number.isInteger(width)) {
|
|
36
|
-
throw new Error(`width must be integer, instead was ${width}`);
|
|
37
|
+
if (!Number.isInteger(width) || itemSize < 0) {
|
|
38
|
+
throw new Error(`width must be a non-negative integer, instead was ${width}`);
|
|
37
39
|
}
|
|
38
|
-
if (!Number.isInteger(height)) {
|
|
39
|
-
throw new Error(`height must be integer, instead was ${height}`);
|
|
40
|
+
if (!Number.isInteger(height) || itemSize < 0) {
|
|
41
|
+
throw new Error(`height must be a non-negative integer, instead was ${height}`);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
if (data === undefined) {
|
|
@@ -523,6 +525,7 @@ export class Sampler2D {
|
|
|
523
525
|
* @returns {number}
|
|
524
526
|
*/
|
|
525
527
|
sampleChannelBilinear(x, y, channel) {
|
|
528
|
+
assert.isNonNegativeInteger(channel, 'channel');
|
|
526
529
|
|
|
527
530
|
const itemSize = this.itemSize;
|
|
528
531
|
|
|
@@ -1099,12 +1102,16 @@ export class Sampler2D {
|
|
|
1099
1102
|
* @param {Number} height
|
|
1100
1103
|
*/
|
|
1101
1104
|
zeroFill(x, y, width, height) {
|
|
1105
|
+
assert.isNonNegativeInteger(width, 'width');
|
|
1106
|
+
assert.isNonNegativeInteger(height, 'height');
|
|
1102
1107
|
|
|
1103
1108
|
const x0 = clamp(x, 0, this.width);
|
|
1104
1109
|
const y0 = clamp(y, 0, this.height);
|
|
1105
1110
|
const x1 = clamp(x + width, 0, this.width);
|
|
1106
1111
|
const y1 = clamp(y + height, 0, this.height);
|
|
1107
1112
|
|
|
1113
|
+
// console.log(`#zerofill x:${x}, y:${y}, width:${width}, height:${height} \t -> \t x0:${x0}, y0:${y0}, x1:${x1}, y1:${y1}`); // DEBUG
|
|
1114
|
+
|
|
1108
1115
|
const data = this.data;
|
|
1109
1116
|
const itemSize = this.itemSize;
|
|
1110
1117
|
|
|
@@ -1432,6 +1439,40 @@ export class Sampler2D {
|
|
|
1432
1439
|
}
|
|
1433
1440
|
}
|
|
1434
1441
|
|
|
1442
|
+
/**
|
|
1443
|
+
*
|
|
1444
|
+
* @param {Sampler2D} other
|
|
1445
|
+
* @return {boolean}
|
|
1446
|
+
*/
|
|
1447
|
+
equals(other) {
|
|
1448
|
+
if (
|
|
1449
|
+
this.width !== other.width
|
|
1450
|
+
|| this.height !== other.height
|
|
1451
|
+
|| this.itemSize !== other.itemSize
|
|
1452
|
+
) {
|
|
1453
|
+
return false;
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
return is_typed_array_equals(this.data, other.data);
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
/**
|
|
1460
|
+
*
|
|
1461
|
+
* @return {number}
|
|
1462
|
+
*/
|
|
1463
|
+
hash() {
|
|
1464
|
+
let hash = (((this.width & 0xFFFF) << 16) | (this.height & 0xFFFF)) ^ this.itemSize;
|
|
1465
|
+
|
|
1466
|
+
const length = this.data.length;
|
|
1467
|
+
|
|
1468
|
+
const stride = Math.max(1, Math.ceil(length / 509));
|
|
1469
|
+
|
|
1470
|
+
hash ^= computeStridedIntegerArrayHash(this.data, 0, length, stride);
|
|
1471
|
+
|
|
1472
|
+
return hash;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
|
|
1435
1476
|
/**
|
|
1436
1477
|
* @returns {Sampler2D}
|
|
1437
1478
|
*/
|
|
@@ -1477,7 +1518,7 @@ export class Sampler2D {
|
|
|
1477
1518
|
|
|
1478
1519
|
this.data = new CTOR(data);
|
|
1479
1520
|
|
|
1480
|
-
}else{
|
|
1521
|
+
} else {
|
|
1481
1522
|
|
|
1482
1523
|
throw new Error('Unsupported data format');
|
|
1483
1524
|
|
|
@@ -9,6 +9,7 @@ import { Transform } from '../../ecs/transform/Transform.js';
|
|
|
9
9
|
import { browserInfo } from "../../Platform.js";
|
|
10
10
|
import Vector3 from "../../../core/geom/Vector3.js";
|
|
11
11
|
import { noop } from "../../../core/function/Functions.js";
|
|
12
|
+
import { assert } from "../../../core/assert.js";
|
|
12
13
|
|
|
13
14
|
const v3 = new Vector3();
|
|
14
15
|
const v3_up = new Vector3();
|
|
@@ -86,6 +87,10 @@ class SoundListenerSystem extends System {
|
|
|
86
87
|
*/
|
|
87
88
|
constructor(context) {
|
|
88
89
|
super();
|
|
90
|
+
|
|
91
|
+
assert.defined(context, 'context');
|
|
92
|
+
assert.isInstanceOf(context, AudioContext, 'context', 'AudioContext');
|
|
93
|
+
|
|
89
94
|
this.dependencies = [SoundListener, Transform];
|
|
90
95
|
//
|
|
91
96
|
this.webAudioContext = context;
|
|
@@ -41,6 +41,11 @@ function volume2dB(volume) {
|
|
|
41
41
|
return 20 * Math.log10(volume);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
const DEFAULT_DISTANCE_MIN = 1;
|
|
45
|
+
const DEFAULT_DISTANCE_MAX = 10000;
|
|
46
|
+
|
|
47
|
+
const DEFAULT_CHANNEL = null;
|
|
48
|
+
|
|
44
49
|
/**
|
|
45
50
|
* @class
|
|
46
51
|
*/
|
|
@@ -61,7 +66,7 @@ export class SoundEmitter {
|
|
|
61
66
|
*
|
|
62
67
|
* @type {String|SoundEmitterChannels|null}
|
|
63
68
|
*/
|
|
64
|
-
this.channel =
|
|
69
|
+
this.channel = DEFAULT_CHANNEL;
|
|
65
70
|
|
|
66
71
|
/**
|
|
67
72
|
*
|
|
@@ -483,6 +488,8 @@ export class SoundEmitter {
|
|
|
483
488
|
|
|
484
489
|
if (json.channel !== undefined) {
|
|
485
490
|
this.channel = json.channel;
|
|
491
|
+
} else {
|
|
492
|
+
this.channel = DEFAULT_CHANNEL;
|
|
486
493
|
}
|
|
487
494
|
|
|
488
495
|
if (json.volume !== undefined) {
|
|
@@ -491,10 +498,14 @@ export class SoundEmitter {
|
|
|
491
498
|
|
|
492
499
|
if (typeof json.distanceMin === "number") {
|
|
493
500
|
this.distanceMin = json.distanceMin;
|
|
501
|
+
} else {
|
|
502
|
+
this.distanceMin = DEFAULT_DISTANCE_MIN;
|
|
494
503
|
}
|
|
495
504
|
|
|
496
505
|
if (typeof json.distanceMax === "number") {
|
|
497
506
|
this.distanceMax = json.distanceMax;
|
|
507
|
+
} else {
|
|
508
|
+
this.distanceMax = DEFAULT_DISTANCE_MAX;
|
|
498
509
|
}
|
|
499
510
|
|
|
500
511
|
if (typeof json.isAttenuated === "boolean") {
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"productName": "Meep",
|
|
6
6
|
"description": "production-ready JavaScript game engine based on Entity Component System Architecture",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.39.
|
|
8
|
+
"version": "2.39.42",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|