@woosh/meep-engine 2.74.0 → 2.75.0
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-image-decoder.js +1 -1
- package/build/meep.cjs +183 -187
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +183 -187
- package/package.json +1 -1
- package/src/core/binary/UINT32_MAX.js +5 -0
- package/src/core/bvh2/bvh3/BVH.js +44 -2
- package/src/core/bvh2/bvh3/BVH.spec.js +45 -0
- package/src/core/bvh2/bvh3/build_triangle_morton_codes.js +73 -0
- package/src/core/bvh2/bvh3/ebvh_build_for_geometry_morton.js +5 -101
- package/src/core/bvh2/bvh3/ebvh_build_hierarchy.js +59 -0
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_nearest_to_point.js +31 -32
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_nearest_to_point.spec.js +64 -0
- package/src/core/collection/SCRATCH_UINT32_TRAVERSAL_STACK.js +1 -0
- package/src/core/geom/3d/aabb/aabb3_signed_distance_sqr_to_point.js +1 -0
- package/src/core/geom/3d/aabb/aabb3_unsigned_distance_sqr_to_point.js +36 -0
- package/src/core/process/worker/OnDemandWorkerManager.js +5 -1
- package/src/engine/asset/loaders/ArrayBufferLoader.js +13 -15
- package/src/engine/asset/loaders/image/ImageDecoderWorker.js +1 -1
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +5 -7
- package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.js +1 -1
- package/src/engine/asset/loaders/image/png/PNG.js +339 -332
- package/src/engine/asset/loaders/image/png/PNGReader.js +59 -16
- package/src/engine/asset/loaders/image/png/prototypePNG.js +13 -4
- package/src/engine/graphics/texture/virtual/v2/{SparseTexture.js → PageTexture.js} +62 -18
- package/src/engine/graphics/texture/virtual/v2/ResidentTileTexture.js +46 -0
- package/src/engine/graphics/texture/virtual/v2/{TileLoader.js → VirtualTextureTileLoader.js} +11 -8
- package/src/engine/graphics/texture/virtual/v2/{UsageMetadata.js → VirtualTextureUsage.js} +2 -8
- package/src/engine/graphics/texture/virtual/v2/{VirtualTextureManager.js → VirtualTextureUsageUpdater.js} +7 -5
- package/src/engine/graphics/texture/virtual/v2/debug/ResidencyDebugView.js +17 -5
- package/src/engine/graphics/texture/virtual/v2/debug/UsageDebugView.js +1 -1
- package/src/engine/graphics/texture/virtual/v2/debug/UsagePyramidDebugView.js +1 -1
- package/src/engine/graphics/texture/virtual/v2/prototype.js +78 -59
- package/src/engine/graphics/texture/virtual/v2/tile/{TextureTile.js → VirtualTextureTile.js} +2 -2
- package/src/engine/graphics/texture/virtual/v2/tile/compose_tile_address.js +4 -0
- /package/src/engine/graphics/texture/virtual/v2/{ShaderUsage.js → VirtualTextureUsageShader.js} +0 -0
package/build/meep.module.js
CHANGED
|
@@ -53658,6 +53658,12 @@ class TerrainPreview {
|
|
|
53658
53658
|
}
|
|
53659
53659
|
}
|
|
53660
53660
|
|
|
53661
|
+
/**
|
|
53662
|
+
* equal to `Math.pow(2,32) - 1`
|
|
53663
|
+
* @type {number}
|
|
53664
|
+
*/
|
|
53665
|
+
const UINT32_MAX = 4294967295;
|
|
53666
|
+
|
|
53661
53667
|
/**
|
|
53662
53668
|
* Assumes arrays have the same type
|
|
53663
53669
|
* @param {TypedArray|Float32Array|Uint8Array|Uint32Array} source
|
|
@@ -53737,6 +53743,13 @@ const ELEMENT_WORD_COUNT = 10;
|
|
|
53737
53743
|
*/
|
|
53738
53744
|
const INITIAL_CAPACITY = 128;
|
|
53739
53745
|
|
|
53746
|
+
|
|
53747
|
+
/**
|
|
53748
|
+
* Tree can not contain more than this number of nodes
|
|
53749
|
+
* @type {number}
|
|
53750
|
+
*/
|
|
53751
|
+
const NODE_CAPACITY_LIMIT = Math.floor(UINT32_MAX / (ELEMENT_WORD_COUNT * 4));
|
|
53752
|
+
|
|
53740
53753
|
/**
|
|
53741
53754
|
* Bounding Volume Hierarchy implementation. Stores unsigned integer values at leaves, these are typically IDs or Index values.
|
|
53742
53755
|
* Highly optimized both in terms of memory usage and CPU. Most of the code inlined. No allocation are performed during usage (except for growing the tree capacity).
|
|
@@ -53831,17 +53844,26 @@ class BVH {
|
|
|
53831
53844
|
}
|
|
53832
53845
|
|
|
53833
53846
|
__grow_capacity() {
|
|
53834
|
-
|
|
53847
|
+
if (this.__capacity >= NODE_CAPACITY_LIMIT) {
|
|
53848
|
+
throw new Error('Can not grow capacity, already at maximum platform limit');
|
|
53849
|
+
}
|
|
53850
|
+
|
|
53851
|
+
let new_capacity = Math.ceil(max2(
|
|
53835
53852
|
this.__capacity * CAPACITY_GROW_MULTIPLIER,
|
|
53836
53853
|
this.__capacity + CAPACITY_GROW_MIN_STEP
|
|
53837
53854
|
));
|
|
53838
53855
|
|
|
53856
|
+
if (new_capacity > NODE_CAPACITY_LIMIT) {
|
|
53857
|
+
// can not grow as much as we'd like, but we can still grow up to the limit
|
|
53858
|
+
new_capacity = NODE_CAPACITY_LIMIT;
|
|
53859
|
+
}
|
|
53860
|
+
|
|
53839
53861
|
this.__set_capacity(new_capacity);
|
|
53840
53862
|
}
|
|
53841
53863
|
|
|
53842
53864
|
/**
|
|
53843
53865
|
*
|
|
53844
|
-
* @param {number} new_capacity
|
|
53866
|
+
* @param {number} new_capacity in number of nodes
|
|
53845
53867
|
* @private
|
|
53846
53868
|
*/
|
|
53847
53869
|
__set_capacity(new_capacity) {
|
|
@@ -54393,6 +54415,9 @@ class BVH {
|
|
|
54393
54415
|
assert.notEqual(child1, NULL_NODE, 'child1 is null');
|
|
54394
54416
|
assert.notEqual(child2, NULL_NODE, 'child2 is null');
|
|
54395
54417
|
|
|
54418
|
+
assert.notEqual(child1, index, 'child1 is equal to parent');
|
|
54419
|
+
assert.notEqual(child2, index, 'child2 is equal to parent');
|
|
54420
|
+
|
|
54396
54421
|
this.node_set_combined_aabb(index, child1, child2);
|
|
54397
54422
|
|
|
54398
54423
|
index = uint32[address + COLUMN_PARENT];
|
|
@@ -54420,6 +54445,9 @@ class BVH {
|
|
|
54420
54445
|
assert.notEqual(child1, NULL_NODE, 'child1 is null');
|
|
54421
54446
|
assert.notEqual(child2, NULL_NODE, 'child2 is null');
|
|
54422
54447
|
|
|
54448
|
+
assert.notEqual(child1, index, 'child1 is equal to parent');
|
|
54449
|
+
assert.notEqual(child2, index, 'child2 is equal to parent');
|
|
54450
|
+
|
|
54423
54451
|
uint32[node_address + COLUMN_HEIGHT] = 1 + max2(
|
|
54424
54452
|
uint32[child1 * ELEMENT_WORD_COUNT + COLUMN_HEIGHT],
|
|
54425
54453
|
uint32[child2 * ELEMENT_WORD_COUNT + COLUMN_HEIGHT],
|
|
@@ -54501,6 +54529,9 @@ class BVH {
|
|
|
54501
54529
|
const iB = uint32[iA * ELEMENT_WORD_COUNT + COLUMN_CHILD_1];
|
|
54502
54530
|
const iC = uint32[iA * ELEMENT_WORD_COUNT + COLUMN_CHILD_2];
|
|
54503
54531
|
|
|
54532
|
+
assert.notEqual(iA, iB, 'child1 equal to parent');
|
|
54533
|
+
assert.notEqual(iA, iB, 'child2 equal to parent');
|
|
54534
|
+
|
|
54504
54535
|
assert.greaterThanOrEqual(iB, 0);
|
|
54505
54536
|
assert.lessThan(iB, this.node_capacity);
|
|
54506
54537
|
assert.greaterThanOrEqual(iC, 0);
|
|
@@ -54516,6 +54547,9 @@ class BVH {
|
|
|
54516
54547
|
const iF = uint32[iC * ELEMENT_WORD_COUNT + COLUMN_CHILD_1];
|
|
54517
54548
|
const iG = uint32[iC * ELEMENT_WORD_COUNT + COLUMN_CHILD_2];
|
|
54518
54549
|
|
|
54550
|
+
assert.notEqual(iC, iF, 'child1 equal to parent');
|
|
54551
|
+
assert.notEqual(iC, iG, 'child2 equal to parent');
|
|
54552
|
+
|
|
54519
54553
|
// b2TreeNode* F = m_nodes + iF;
|
|
54520
54554
|
// b2TreeNode* G = m_nodes + iG;
|
|
54521
54555
|
|
|
@@ -54534,6 +54568,7 @@ class BVH {
|
|
|
54534
54568
|
|
|
54535
54569
|
// A's old parent should point to C
|
|
54536
54570
|
if (a_parent !== NULL_NODE) {
|
|
54571
|
+
assert.notEqual(a_parent, iC);
|
|
54537
54572
|
if (uint32[a_parent * ELEMENT_WORD_COUNT + COLUMN_CHILD_1] === iA) {
|
|
54538
54573
|
uint32[a_parent * ELEMENT_WORD_COUNT + COLUMN_CHILD_1] = iC;
|
|
54539
54574
|
} else {
|
|
@@ -54586,6 +54621,9 @@ class BVH {
|
|
|
54586
54621
|
|
|
54587
54622
|
}
|
|
54588
54623
|
|
|
54624
|
+
assert.notEqual(iC, uint32[iC * ELEMENT_WORD_COUNT + COLUMN_CHILD_1]);
|
|
54625
|
+
assert.notEqual(iC, uint32[iC * ELEMENT_WORD_COUNT + COLUMN_CHILD_2]);
|
|
54626
|
+
|
|
54589
54627
|
return iC;
|
|
54590
54628
|
}
|
|
54591
54629
|
|
|
@@ -54594,6 +54632,9 @@ class BVH {
|
|
|
54594
54632
|
const iD = uint32[iB * ELEMENT_WORD_COUNT + COLUMN_CHILD_1];
|
|
54595
54633
|
const iE = uint32[iB * ELEMENT_WORD_COUNT + COLUMN_CHILD_2];
|
|
54596
54634
|
|
|
54635
|
+
assert.notEqual(iB, iD, 'child1 equal to parent');
|
|
54636
|
+
assert.notEqual(iB, iE, 'child2 equal to parent');
|
|
54637
|
+
|
|
54597
54638
|
assert.greaterThanOrEqual(iD, 0);
|
|
54598
54639
|
assert.lessThan(iD, this.node_capacity);
|
|
54599
54640
|
assert.greaterThanOrEqual(iE, 0);
|
|
@@ -54660,9 +54701,15 @@ class BVH {
|
|
|
54660
54701
|
|
|
54661
54702
|
}
|
|
54662
54703
|
|
|
54704
|
+
assert.notEqual(iB, uint32[iB * ELEMENT_WORD_COUNT + COLUMN_CHILD_1]);
|
|
54705
|
+
assert.notEqual(iB, uint32[iB * ELEMENT_WORD_COUNT + COLUMN_CHILD_2]);
|
|
54706
|
+
|
|
54663
54707
|
return iB;
|
|
54664
54708
|
}
|
|
54665
54709
|
|
|
54710
|
+
assert.notEqual(iA, uint32[iA * ELEMENT_WORD_COUNT + COLUMN_CHILD_1]);
|
|
54711
|
+
assert.notEqual(iA, uint32[iA * ELEMENT_WORD_COUNT + COLUMN_CHILD_2]);
|
|
54712
|
+
|
|
54666
54713
|
// no rotation
|
|
54667
54714
|
return iA;
|
|
54668
54715
|
}
|
|
@@ -54823,6 +54870,7 @@ const SCRATCH_UINT32_TRAVERSAL_STACK = new Uint32Array(781250);
|
|
|
54823
54870
|
|
|
54824
54871
|
/**
|
|
54825
54872
|
* Pointer used to track current top of the stack, make sure to unwind once your traversal is done
|
|
54873
|
+
* Must be a positive integer
|
|
54826
54874
|
* @type {number}
|
|
54827
54875
|
*/
|
|
54828
54876
|
SCRATCH_UINT32_TRAVERSAL_STACK.pointer = 0;
|
|
@@ -68900,50 +68948,49 @@ function bvh_query_user_data_overlaps_frustum(
|
|
|
68900
68948
|
return result_cursor - result_offset;
|
|
68901
68949
|
}
|
|
68902
68950
|
|
|
68951
|
+
const PATH_SEPARATOR = '/';
|
|
68952
|
+
|
|
68903
68953
|
/**
|
|
68904
|
-
*
|
|
68905
|
-
* @
|
|
68954
|
+
* Strips all directories from the path.
|
|
68955
|
+
* @example 'a/b/c' -> 'c'
|
|
68956
|
+
* @param {string} path
|
|
68957
|
+
* @returns {string}
|
|
68906
68958
|
*/
|
|
68907
|
-
|
|
68908
|
-
|
|
68909
|
-
|
|
68910
|
-
|
|
68911
|
-
*/
|
|
68912
|
-
assetManager = null;
|
|
68959
|
+
function computePathBase(path) {
|
|
68960
|
+
if (typeof path !== "string") {
|
|
68961
|
+
throw new Error('path is not a string');
|
|
68962
|
+
}
|
|
68913
68963
|
|
|
68914
|
-
|
|
68915
|
-
*
|
|
68916
|
-
* @type {CTX}
|
|
68917
|
-
*/
|
|
68918
|
-
context = null;
|
|
68964
|
+
const lastSlashIndex = path.lastIndexOf(PATH_SEPARATOR);
|
|
68919
68965
|
|
|
68920
|
-
|
|
68921
|
-
|
|
68922
|
-
|
|
68923
|
-
|
|
68924
|
-
|
|
68925
|
-
|
|
68926
|
-
|
|
68927
|
-
|
|
68966
|
+
if (lastSlashIndex !== -1) {
|
|
68967
|
+
return path.substring(lastSlashIndex + 1);
|
|
68968
|
+
} else {
|
|
68969
|
+
return path;
|
|
68970
|
+
}
|
|
68971
|
+
}
|
|
68972
|
+
|
|
68973
|
+
/**
|
|
68974
|
+
*
|
|
68975
|
+
* @param {string} path
|
|
68976
|
+
* @returns {String|null}
|
|
68977
|
+
*/
|
|
68978
|
+
function computeFileExtension(path) {
|
|
68979
|
+
const type_of_path = typeof path;
|
|
68980
|
+
if (type_of_path !== "string") {
|
|
68981
|
+
throw new Error(`path must be a string, instead was '${type_of_path}'`);
|
|
68928
68982
|
}
|
|
68929
68983
|
|
|
68930
|
-
|
|
68931
|
-
|
|
68932
|
-
*/
|
|
68933
|
-
async unlink() {
|
|
68984
|
+
//get base
|
|
68985
|
+
const pathBase = computePathBase(path);
|
|
68934
68986
|
|
|
68935
|
-
|
|
68987
|
+
const lastDotIndex = pathBase.lastIndexOf('.');
|
|
68936
68988
|
|
|
68937
|
-
|
|
68938
|
-
|
|
68939
|
-
|
|
68940
|
-
|
|
68941
|
-
|
|
68942
|
-
* @param {function} failure
|
|
68943
|
-
* @param {function(current:number, total:number)} progress
|
|
68944
|
-
*/
|
|
68945
|
-
load(scope, path, success, failure, progress) {
|
|
68946
|
-
failure('Not Implemented');
|
|
68989
|
+
if (lastDotIndex !== -1) {
|
|
68990
|
+
return pathBase.substring(lastDotIndex + 1);
|
|
68991
|
+
} else {
|
|
68992
|
+
//no extension
|
|
68993
|
+
return null;
|
|
68947
68994
|
}
|
|
68948
68995
|
}
|
|
68949
68996
|
|
|
@@ -69154,49 +69201,6 @@ class Asset {
|
|
|
69154
69201
|
|
|
69155
69202
|
Asset.prototype.byteSize = 0;
|
|
69156
69203
|
|
|
69157
|
-
class ImageRGBADataAsset extends Asset {
|
|
69158
|
-
/**
|
|
69159
|
-
*
|
|
69160
|
-
* @param {number[]|Uint8Array} data
|
|
69161
|
-
* @param {number} width
|
|
69162
|
-
* @param {number} height
|
|
69163
|
-
* @param {number} [itemSize]
|
|
69164
|
-
*/
|
|
69165
|
-
constructor(data, width, height, itemSize = 4) {
|
|
69166
|
-
super();
|
|
69167
|
-
|
|
69168
|
-
/**
|
|
69169
|
-
*
|
|
69170
|
-
* @type {number[]}
|
|
69171
|
-
*/
|
|
69172
|
-
this.data = data;
|
|
69173
|
-
|
|
69174
|
-
/**
|
|
69175
|
-
*
|
|
69176
|
-
* @type {number}
|
|
69177
|
-
*/
|
|
69178
|
-
this.width = width;
|
|
69179
|
-
|
|
69180
|
-
/**
|
|
69181
|
-
*
|
|
69182
|
-
* @type {number}
|
|
69183
|
-
*/
|
|
69184
|
-
this.height = height;
|
|
69185
|
-
|
|
69186
|
-
/**
|
|
69187
|
-
* Number of channels
|
|
69188
|
-
* @type {number}
|
|
69189
|
-
*/
|
|
69190
|
-
this.itemSize = itemSize;
|
|
69191
|
-
|
|
69192
|
-
this.byteSize = data.length;
|
|
69193
|
-
}
|
|
69194
|
-
|
|
69195
|
-
create() {
|
|
69196
|
-
return new Sampler2D(this.data, this.itemSize, this.width, this.height);
|
|
69197
|
-
}
|
|
69198
|
-
}
|
|
69199
|
-
|
|
69200
69204
|
const CrossOriginKind = {
|
|
69201
69205
|
UseCredentials: 'use-credentials',
|
|
69202
69206
|
Anonymous: 'anonymous'
|
|
@@ -69212,6 +69216,53 @@ class CrossOriginConfig {
|
|
|
69212
69216
|
const default_coc = new CrossOriginConfig();
|
|
69213
69217
|
CrossOriginConfig.default = Object.freeze(default_coc);
|
|
69214
69218
|
|
|
69219
|
+
/**
|
|
69220
|
+
* @template CTX
|
|
69221
|
+
* @template Asset
|
|
69222
|
+
*/
|
|
69223
|
+
class AssetLoader {
|
|
69224
|
+
/**
|
|
69225
|
+
*
|
|
69226
|
+
* @type {AssetManager}
|
|
69227
|
+
*/
|
|
69228
|
+
assetManager = null;
|
|
69229
|
+
|
|
69230
|
+
/**
|
|
69231
|
+
*
|
|
69232
|
+
* @type {CTX}
|
|
69233
|
+
*/
|
|
69234
|
+
context = null;
|
|
69235
|
+
|
|
69236
|
+
/**
|
|
69237
|
+
*
|
|
69238
|
+
* @param {AssetManager} assetManager
|
|
69239
|
+
* @param {CTX} context
|
|
69240
|
+
*/
|
|
69241
|
+
async link(assetManager, context) {
|
|
69242
|
+
this.assetManager = assetManager;
|
|
69243
|
+
this.context = context;
|
|
69244
|
+
}
|
|
69245
|
+
|
|
69246
|
+
/**
|
|
69247
|
+
* Release any held resources, finalizing operation of the loader
|
|
69248
|
+
*/
|
|
69249
|
+
async unlink() {
|
|
69250
|
+
|
|
69251
|
+
}
|
|
69252
|
+
|
|
69253
|
+
/**
|
|
69254
|
+
*
|
|
69255
|
+
* @param {AssetRequestScope} scope
|
|
69256
|
+
* @param {string} path
|
|
69257
|
+
* @param {function(Asset)} success
|
|
69258
|
+
* @param {function} failure
|
|
69259
|
+
* @param {function(current:number, total:number)} progress
|
|
69260
|
+
*/
|
|
69261
|
+
load(scope, path, success, failure, progress) {
|
|
69262
|
+
failure('Not Implemented');
|
|
69263
|
+
}
|
|
69264
|
+
}
|
|
69265
|
+
|
|
69215
69266
|
class ArrayBufferLoader extends AssetLoader {
|
|
69216
69267
|
/**
|
|
69217
69268
|
*
|
|
@@ -69296,33 +69347,33 @@ class ArrayBufferLoader extends AssetLoader {
|
|
|
69296
69347
|
}
|
|
69297
69348
|
|
|
69298
69349
|
const reader = response.body.getReader();
|
|
69299
|
-
response.headers.get('Content-Length');
|
|
69350
|
+
const contentLength = response.headers.get('Content-Length');
|
|
69351
|
+
const total = contentLength ? parseInt(contentLength) : 0;
|
|
69300
69352
|
let loaded = 0;
|
|
69301
69353
|
|
|
69302
69354
|
// periodically read data into the new stream tracking while download progress
|
|
69303
69355
|
const stream = new ReadableStream({
|
|
69356
|
+
type: "bytes",
|
|
69304
69357
|
start(controller) {
|
|
69305
69358
|
|
|
69306
|
-
|
|
69359
|
+
pump();
|
|
69307
69360
|
|
|
69308
|
-
function
|
|
69361
|
+
function pump() {
|
|
69309
69362
|
|
|
69310
69363
|
reader.read().then(({ done, value }) => {
|
|
69311
69364
|
|
|
69312
69365
|
if (done) {
|
|
69313
|
-
|
|
69366
|
+
// no more data, we're done
|
|
69314
69367
|
controller.close();
|
|
69368
|
+
return;
|
|
69369
|
+
}
|
|
69315
69370
|
|
|
69316
|
-
|
|
69317
|
-
|
|
69318
|
-
loaded += value.byteLength;
|
|
69319
|
-
|
|
69320
|
-
progress(loaded, length);
|
|
69371
|
+
loaded += value.byteLength;
|
|
69321
69372
|
|
|
69322
|
-
|
|
69323
|
-
readData();
|
|
69373
|
+
progress(loaded, total);
|
|
69324
69374
|
|
|
69325
|
-
|
|
69375
|
+
controller.enqueue(value);
|
|
69376
|
+
pump();
|
|
69326
69377
|
|
|
69327
69378
|
});
|
|
69328
69379
|
|
|
@@ -69466,6 +69517,10 @@ class OnDemandWorkerManager {
|
|
|
69466
69517
|
this.worker = worker;
|
|
69467
69518
|
}
|
|
69468
69519
|
|
|
69520
|
+
/**
|
|
69521
|
+
* In milliseconds
|
|
69522
|
+
* @param {number} v
|
|
69523
|
+
*/
|
|
69469
69524
|
setTimeout(v) {
|
|
69470
69525
|
assert.isNonNegativeInteger(v, 'v');
|
|
69471
69526
|
|
|
@@ -69572,7 +69627,7 @@ class ThreadedImageDecoder extends Codec {
|
|
|
69572
69627
|
*/
|
|
69573
69628
|
this.worker = new OnDemandWorkerManager(workerBuilder.build());
|
|
69574
69629
|
|
|
69575
|
-
this.worker.setTimeout(
|
|
69630
|
+
this.worker.setTimeout(1200);
|
|
69576
69631
|
}
|
|
69577
69632
|
|
|
69578
69633
|
async test(data) {
|
|
@@ -69591,104 +69646,46 @@ class ThreadedImageDecoder extends Codec {
|
|
|
69591
69646
|
}
|
|
69592
69647
|
}
|
|
69593
69648
|
|
|
69594
|
-
|
|
69595
|
-
|
|
69596
|
-
|
|
69597
|
-
|
|
69598
|
-
|
|
69599
|
-
|
|
69600
|
-
|
|
69601
|
-
|
|
69602
|
-
|
|
69603
|
-
|
|
69604
|
-
const canvas = document.createElement('canvas');
|
|
69605
|
-
|
|
69606
|
-
canvas.width = imgWidth;
|
|
69607
|
-
canvas.height = imgHeight;
|
|
69608
|
-
|
|
69609
|
-
const context = canvas.getContext('2d');
|
|
69610
|
-
|
|
69611
|
-
context.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
69612
|
-
|
|
69613
|
-
const imgd = context.getImageData(0, 0, imgWidth, imgHeight);
|
|
69614
|
-
|
|
69615
|
-
return imgd.data;
|
|
69616
|
-
}
|
|
69617
|
-
|
|
69618
|
-
class NativeImageDecoder extends Codec {
|
|
69619
|
-
async decode(data) {
|
|
69620
|
-
const image = new Image();
|
|
69621
|
-
|
|
69622
|
-
// convert binary data to image URL that we can load
|
|
69623
|
-
const blob = new Blob([data]);
|
|
69624
|
-
const url = URL.createObjectURL(blob);
|
|
69625
|
-
|
|
69626
|
-
image.src = url;
|
|
69627
|
-
|
|
69628
|
-
// give browser a chance to decode image in async
|
|
69629
|
-
await image.decode();
|
|
69630
|
-
|
|
69631
|
-
const rgba_data = decode(image);
|
|
69649
|
+
class ImageRGBADataAsset extends Asset {
|
|
69650
|
+
/**
|
|
69651
|
+
*
|
|
69652
|
+
* @param {number[]|Uint8Array} data
|
|
69653
|
+
* @param {number} width
|
|
69654
|
+
* @param {number} height
|
|
69655
|
+
* @param {number} [itemSize]
|
|
69656
|
+
*/
|
|
69657
|
+
constructor(data, width, height, itemSize = 4) {
|
|
69658
|
+
super();
|
|
69632
69659
|
|
|
69633
|
-
|
|
69634
|
-
|
|
69660
|
+
/**
|
|
69661
|
+
*
|
|
69662
|
+
* @type {number[]}
|
|
69663
|
+
*/
|
|
69664
|
+
this.data = data;
|
|
69635
69665
|
|
|
69636
|
-
|
|
69637
|
-
|
|
69666
|
+
/**
|
|
69667
|
+
*
|
|
69668
|
+
* @type {number}
|
|
69669
|
+
*/
|
|
69670
|
+
this.width = width;
|
|
69638
69671
|
|
|
69639
|
-
|
|
69640
|
-
|
|
69641
|
-
|
|
69642
|
-
|
|
69643
|
-
|
|
69644
|
-
bitDepth: 8
|
|
69645
|
-
};
|
|
69646
|
-
}
|
|
69647
|
-
}
|
|
69648
|
-
|
|
69649
|
-
const PATH_SEPARATOR = '/';
|
|
69650
|
-
|
|
69651
|
-
/**
|
|
69652
|
-
* Strips all directories from the path.
|
|
69653
|
-
* @example 'a/b/c' -> 'c'
|
|
69654
|
-
* @param {string} path
|
|
69655
|
-
* @returns {string}
|
|
69656
|
-
*/
|
|
69657
|
-
function computePathBase(path) {
|
|
69658
|
-
if (typeof path !== "string") {
|
|
69659
|
-
throw new Error('path is not a string');
|
|
69660
|
-
}
|
|
69672
|
+
/**
|
|
69673
|
+
*
|
|
69674
|
+
* @type {number}
|
|
69675
|
+
*/
|
|
69676
|
+
this.height = height;
|
|
69661
69677
|
|
|
69662
|
-
|
|
69678
|
+
/**
|
|
69679
|
+
* Number of channels
|
|
69680
|
+
* @type {number}
|
|
69681
|
+
*/
|
|
69682
|
+
this.itemSize = itemSize;
|
|
69663
69683
|
|
|
69664
|
-
|
|
69665
|
-
return path.substring(lastSlashIndex + 1);
|
|
69666
|
-
} else {
|
|
69667
|
-
return path;
|
|
69668
|
-
}
|
|
69669
|
-
}
|
|
69670
|
-
|
|
69671
|
-
/**
|
|
69672
|
-
*
|
|
69673
|
-
* @param {string} path
|
|
69674
|
-
* @returns {String|null}
|
|
69675
|
-
*/
|
|
69676
|
-
function computeFileExtension(path) {
|
|
69677
|
-
const type_of_path = typeof path;
|
|
69678
|
-
if (type_of_path !== "string") {
|
|
69679
|
-
throw new Error(`path must be a string, instead was '${type_of_path}'`);
|
|
69684
|
+
this.byteSize = data.length;
|
|
69680
69685
|
}
|
|
69681
69686
|
|
|
69682
|
-
|
|
69683
|
-
|
|
69684
|
-
|
|
69685
|
-
const lastDotIndex = pathBase.lastIndexOf('.');
|
|
69686
|
-
|
|
69687
|
-
if (lastDotIndex !== -1) {
|
|
69688
|
-
return pathBase.substring(lastDotIndex + 1);
|
|
69689
|
-
} else {
|
|
69690
|
-
//no extension
|
|
69691
|
-
return null;
|
|
69687
|
+
create() {
|
|
69688
|
+
return new Sampler2D(this.data, this.itemSize, this.width, this.height);
|
|
69692
69689
|
}
|
|
69693
69690
|
}
|
|
69694
69691
|
|
|
@@ -69700,7 +69697,7 @@ class ImageRGBADataLoader extends AssetLoader {
|
|
|
69700
69697
|
|
|
69701
69698
|
this.decoder = new CodecWithFallback(
|
|
69702
69699
|
new ThreadedImageDecoder(),
|
|
69703
|
-
new NativeImageDecoder()
|
|
69700
|
+
// new NativeImageDecoder()
|
|
69704
69701
|
);
|
|
69705
69702
|
}
|
|
69706
69703
|
|
|
@@ -69742,7 +69739,6 @@ class ImageRGBADataLoader extends AssetLoader {
|
|
|
69742
69739
|
|
|
69743
69740
|
const bitmap = await this.__decode_via_worker(path, scope);
|
|
69744
69741
|
|
|
69745
|
-
|
|
69746
69742
|
let data;
|
|
69747
69743
|
|
|
69748
69744
|
const bitDepth = bitmap.bitDepth;
|
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { assert } from "../../assert.js";
|
|
2
|
+
import { UINT32_MAX } from "../../binary/UINT32_MAX.js";
|
|
2
3
|
import { array_copy } from "../../collection/array/array_copy.js";
|
|
3
4
|
import { typed_array_copy } from "../../collection/array/typed/typed_array_copy.js";
|
|
4
5
|
import { aabb3_compute_surface_area } from "../../geom/3d/aabb/aabb3_compute_surface_area.js";
|
|
@@ -51,6 +52,13 @@ export const ELEMENT_WORD_COUNT = 10;
|
|
|
51
52
|
*/
|
|
52
53
|
const INITIAL_CAPACITY = 128;
|
|
53
54
|
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Tree can not contain more than this number of nodes
|
|
58
|
+
* @type {number}
|
|
59
|
+
*/
|
|
60
|
+
const NODE_CAPACITY_LIMIT = Math.floor(UINT32_MAX / (ELEMENT_WORD_COUNT * 4));
|
|
61
|
+
|
|
54
62
|
/**
|
|
55
63
|
* Bounding Volume Hierarchy implementation. Stores unsigned integer values at leaves, these are typically IDs or Index values.
|
|
56
64
|
* Highly optimized both in terms of memory usage and CPU. Most of the code inlined. No allocation are performed during usage (except for growing the tree capacity).
|
|
@@ -145,17 +153,26 @@ export class BVH {
|
|
|
145
153
|
}
|
|
146
154
|
|
|
147
155
|
__grow_capacity() {
|
|
148
|
-
|
|
156
|
+
if (this.__capacity >= NODE_CAPACITY_LIMIT) {
|
|
157
|
+
throw new Error('Can not grow capacity, already at maximum platform limit');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
let new_capacity = Math.ceil(max2(
|
|
149
161
|
this.__capacity * CAPACITY_GROW_MULTIPLIER,
|
|
150
162
|
this.__capacity + CAPACITY_GROW_MIN_STEP
|
|
151
163
|
));
|
|
152
164
|
|
|
165
|
+
if (new_capacity > NODE_CAPACITY_LIMIT) {
|
|
166
|
+
// can not grow as much as we'd like, but we can still grow up to the limit
|
|
167
|
+
new_capacity = NODE_CAPACITY_LIMIT;
|
|
168
|
+
}
|
|
169
|
+
|
|
153
170
|
this.__set_capacity(new_capacity);
|
|
154
171
|
}
|
|
155
172
|
|
|
156
173
|
/**
|
|
157
174
|
*
|
|
158
|
-
* @param {number} new_capacity
|
|
175
|
+
* @param {number} new_capacity in number of nodes
|
|
159
176
|
* @private
|
|
160
177
|
*/
|
|
161
178
|
__set_capacity(new_capacity) {
|
|
@@ -707,6 +724,9 @@ export class BVH {
|
|
|
707
724
|
assert.notEqual(child1, NULL_NODE, 'child1 is null');
|
|
708
725
|
assert.notEqual(child2, NULL_NODE, 'child2 is null');
|
|
709
726
|
|
|
727
|
+
assert.notEqual(child1, index, 'child1 is equal to parent');
|
|
728
|
+
assert.notEqual(child2, index, 'child2 is equal to parent');
|
|
729
|
+
|
|
710
730
|
this.node_set_combined_aabb(index, child1, child2);
|
|
711
731
|
|
|
712
732
|
index = uint32[address + COLUMN_PARENT];
|
|
@@ -734,6 +754,9 @@ export class BVH {
|
|
|
734
754
|
assert.notEqual(child1, NULL_NODE, 'child1 is null');
|
|
735
755
|
assert.notEqual(child2, NULL_NODE, 'child2 is null');
|
|
736
756
|
|
|
757
|
+
assert.notEqual(child1, index, 'child1 is equal to parent');
|
|
758
|
+
assert.notEqual(child2, index, 'child2 is equal to parent');
|
|
759
|
+
|
|
737
760
|
uint32[node_address + COLUMN_HEIGHT] = 1 + max2(
|
|
738
761
|
uint32[child1 * ELEMENT_WORD_COUNT + COLUMN_HEIGHT],
|
|
739
762
|
uint32[child2 * ELEMENT_WORD_COUNT + COLUMN_HEIGHT],
|
|
@@ -815,6 +838,9 @@ export class BVH {
|
|
|
815
838
|
const iB = uint32[iA * ELEMENT_WORD_COUNT + COLUMN_CHILD_1];
|
|
816
839
|
const iC = uint32[iA * ELEMENT_WORD_COUNT + COLUMN_CHILD_2];
|
|
817
840
|
|
|
841
|
+
assert.notEqual(iA, iB, 'child1 equal to parent');
|
|
842
|
+
assert.notEqual(iA, iB, 'child2 equal to parent');
|
|
843
|
+
|
|
818
844
|
assert.greaterThanOrEqual(iB, 0);
|
|
819
845
|
assert.lessThan(iB, this.node_capacity);
|
|
820
846
|
assert.greaterThanOrEqual(iC, 0);
|
|
@@ -830,6 +856,9 @@ export class BVH {
|
|
|
830
856
|
const iF = uint32[iC * ELEMENT_WORD_COUNT + COLUMN_CHILD_1];
|
|
831
857
|
const iG = uint32[iC * ELEMENT_WORD_COUNT + COLUMN_CHILD_2];
|
|
832
858
|
|
|
859
|
+
assert.notEqual(iC, iF, 'child1 equal to parent');
|
|
860
|
+
assert.notEqual(iC, iG, 'child2 equal to parent');
|
|
861
|
+
|
|
833
862
|
// b2TreeNode* F = m_nodes + iF;
|
|
834
863
|
// b2TreeNode* G = m_nodes + iG;
|
|
835
864
|
|
|
@@ -848,6 +877,7 @@ export class BVH {
|
|
|
848
877
|
|
|
849
878
|
// A's old parent should point to C
|
|
850
879
|
if (a_parent !== NULL_NODE) {
|
|
880
|
+
assert.notEqual(a_parent, iC);
|
|
851
881
|
if (uint32[a_parent * ELEMENT_WORD_COUNT + COLUMN_CHILD_1] === iA) {
|
|
852
882
|
uint32[a_parent * ELEMENT_WORD_COUNT + COLUMN_CHILD_1] = iC;
|
|
853
883
|
} else {
|
|
@@ -900,6 +930,9 @@ export class BVH {
|
|
|
900
930
|
|
|
901
931
|
}
|
|
902
932
|
|
|
933
|
+
assert.notEqual(iC, uint32[iC * ELEMENT_WORD_COUNT + COLUMN_CHILD_1]);
|
|
934
|
+
assert.notEqual(iC, uint32[iC * ELEMENT_WORD_COUNT + COLUMN_CHILD_2]);
|
|
935
|
+
|
|
903
936
|
return iC;
|
|
904
937
|
}
|
|
905
938
|
|
|
@@ -908,6 +941,9 @@ export class BVH {
|
|
|
908
941
|
const iD = uint32[iB * ELEMENT_WORD_COUNT + COLUMN_CHILD_1];
|
|
909
942
|
const iE = uint32[iB * ELEMENT_WORD_COUNT + COLUMN_CHILD_2];
|
|
910
943
|
|
|
944
|
+
assert.notEqual(iB, iD, 'child1 equal to parent');
|
|
945
|
+
assert.notEqual(iB, iE, 'child2 equal to parent');
|
|
946
|
+
|
|
911
947
|
assert.greaterThanOrEqual(iD, 0);
|
|
912
948
|
assert.lessThan(iD, this.node_capacity);
|
|
913
949
|
assert.greaterThanOrEqual(iE, 0);
|
|
@@ -974,9 +1010,15 @@ export class BVH {
|
|
|
974
1010
|
|
|
975
1011
|
}
|
|
976
1012
|
|
|
1013
|
+
assert.notEqual(iB, uint32[iB * ELEMENT_WORD_COUNT + COLUMN_CHILD_1]);
|
|
1014
|
+
assert.notEqual(iB, uint32[iB * ELEMENT_WORD_COUNT + COLUMN_CHILD_2]);
|
|
1015
|
+
|
|
977
1016
|
return iB;
|
|
978
1017
|
}
|
|
979
1018
|
|
|
1019
|
+
assert.notEqual(iA, uint32[iA * ELEMENT_WORD_COUNT + COLUMN_CHILD_1]);
|
|
1020
|
+
assert.notEqual(iA, uint32[iA * ELEMENT_WORD_COUNT + COLUMN_CHILD_2]);
|
|
1021
|
+
|
|
980
1022
|
// no rotation
|
|
981
1023
|
return iA;
|
|
982
1024
|
}
|