@xeokit/xeokit-sdk 2.3.0-beta-11 → 2.3.0-beta-16

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.
@@ -15295,7 +15295,7 @@ class RenderBufferManager {
15295
15295
  /**
15296
15296
  * @private
15297
15297
  */
15298
- function getExtension$1 (gl, name) {
15298
+ function getExtension (gl, name) {
15299
15299
  if (gl._cachedExtensions === undefined) {
15300
15300
  gl._cachedExtensions = {};
15301
15301
  }
@@ -15361,12 +15361,12 @@ const Renderer = function (scene, options) {
15361
15361
  this._occlusionTester = null; // Lazy-created in #addMarker()
15362
15362
 
15363
15363
  this.capabilities = {
15364
- astcSupported: !!getExtension$1(gl, 'WEBGL_compressed_texture_astc'),
15364
+ astcSupported: !!getExtension(gl, 'WEBGL_compressed_texture_astc'),
15365
15365
  etc1Supported: true, // WebGL2
15366
- etc2Supported: !!getExtension$1(gl, 'WEBGL_compressed_texture_etc'),
15367
- dxtSupported: !!getExtension$1(gl, 'WEBGL_compressed_texture_s3tc'),
15368
- bptcSupported: !!getExtension$1(gl, 'EXT_texture_compression_bptc'),
15369
- pvrtcSupported: !!(getExtension$1(gl, 'WEBGL_compressed_texture_pvrtc') || getExtension$1(gl, 'WEBKIT_WEBGL_compressed_texture_pvrtc'))
15366
+ etc2Supported: !!getExtension(gl, 'WEBGL_compressed_texture_etc'),
15367
+ dxtSupported: !!getExtension(gl, 'WEBGL_compressed_texture_s3tc'),
15368
+ bptcSupported: !!getExtension(gl, 'EXT_texture_compression_bptc'),
15369
+ pvrtcSupported: !!(getExtension(gl, 'WEBGL_compressed_texture_pvrtc') || getExtension(gl, 'WEBKIT_WEBGL_compressed_texture_pvrtc'))
15370
15370
  };
15371
15371
 
15372
15372
  this.setTransparentEnabled = function (enabled) {
@@ -15995,22 +15995,6 @@ const Renderer = function (scene, options) {
15995
15995
  gl.depthMask(false);
15996
15996
  }
15997
15997
 
15998
- // Transparent X-ray edges
15999
-
16000
- if (xrayEdgesTransparentBinLen > 0) {
16001
- for (i = 0; i < xrayEdgesTransparentBinLen; i++) {
16002
- xrayEdgesTransparentBin[i].drawEdgesXRayed(frameCtx);
16003
- }
16004
- }
16005
-
16006
- // Transparent X-ray fill
16007
-
16008
- if (xrayedFillTransparentBinLen > 0) {
16009
- for (i = 0; i < xrayedFillTransparentBinLen; i++) {
16010
- xrayedFillTransparentBin[i].drawSilhouetteXRayed(frameCtx);
16011
- }
16012
- }
16013
-
16014
15998
  // Transparent color edges
16015
15999
 
16016
16000
  if (normalFillTransparentBinLen > 0 || normalEdgesTransparentBinLen > 0) {
@@ -16031,6 +16015,23 @@ const Renderer = function (scene, options) {
16031
16015
  drawable.drawColorTransparent(frameCtx);
16032
16016
  }
16033
16017
  }
16018
+
16019
+ // Transparent X-ray edges
16020
+
16021
+ if (xrayEdgesTransparentBinLen > 0) {
16022
+ for (i = 0; i < xrayEdgesTransparentBinLen; i++) {
16023
+ xrayEdgesTransparentBin[i].drawEdgesXRayed(frameCtx);
16024
+ }
16025
+ }
16026
+
16027
+ // Transparent X-ray fill
16028
+
16029
+ if (xrayedFillTransparentBinLen > 0) {
16030
+ for (i = 0; i < xrayedFillTransparentBinLen; i++) {
16031
+ xrayedFillTransparentBin[i].drawSilhouetteXRayed(frameCtx);
16032
+ }
16033
+ }
16034
+
16034
16035
  gl.disable(gl.BLEND);
16035
16036
  if (!alphaDepthMask) {
16036
16037
  gl.depthMask(true);
@@ -27797,6 +27798,7 @@ const ClampToEdgeWrapping = 1001;
27797
27798
  const MirroredRepeatWrapping = 1002;
27798
27799
  const NearestFilter = 1003;
27799
27800
  const NearestMipMapNearestFilter = 1004;
27801
+ const NearestMipmapNearestFilter = 1004;
27800
27802
  const NearestMipmapLinearFilter = 1005;
27801
27803
  const NearestMipMapLinearFilter = 1005;
27802
27804
  const LinearFilter = 1006;
@@ -46501,29 +46503,29 @@ function transformAndOctEncodeNormals(worldNormalMatrix, normals, lenNormals, co
46501
46503
  function octEncodeNormals(normals) { // http://jcgt.org/published/0003/02/01/
46502
46504
  const lenNormals = normals.length;
46503
46505
  const compressedNormals = new Int8Array(lenNormals);
46504
- let oct, best, currentCos, bestCos;
46506
+ let oct, dec, best, currentCos, bestCos;
46505
46507
  for (let i = 0; i < lenNormals; i += 3) {
46506
46508
  // Test various combinations of ceil and floor to minimize rounding errors
46507
46509
  best = oct = octEncodeNormal(normals, i, "floor", "floor");
46508
- octDecodeVec2(oct);
46509
- currentCos = bestCos = dot(normals, i);
46510
+ dec = octDecodeVec2(oct);
46511
+ currentCos = bestCos = dot(normals, i, dec);
46510
46512
  oct = octEncodeNormal(normals, i, "ceil", "floor");
46511
- octDecodeVec2(oct);
46512
- currentCos = dot(normals, i);
46513
+ dec = octDecodeVec2(oct);
46514
+ currentCos = dot(normals, i, dec);
46513
46515
  if (currentCos > bestCos) {
46514
46516
  best = oct;
46515
46517
  bestCos = currentCos;
46516
46518
  }
46517
46519
  oct = octEncodeNormal(normals, i, "floor", "ceil");
46518
- octDecodeVec2(oct);
46519
- currentCos = dot(normals, i);
46520
+ dec = octDecodeVec2(oct);
46521
+ currentCos = dot(normals, i, dec);
46520
46522
  if (currentCos > bestCos) {
46521
46523
  best = oct;
46522
46524
  bestCos = currentCos;
46523
46525
  }
46524
46526
  oct = octEncodeNormal(normals, i, "ceil", "ceil");
46525
- octDecodeVec2(oct);
46526
- currentCos = dot(normals, i);
46527
+ dec = octDecodeVec2(oct);
46528
+ currentCos = dot(normals, i, dec);
46527
46529
  if (currentCos > bestCos) {
46528
46530
  best = oct;
46529
46531
  bestCos = currentCos;
@@ -46597,8 +46599,8 @@ function octDecodeVec2(oct) { // Decode an oct-encoded normal
46597
46599
  /**
46598
46600
  * @private
46599
46601
  */
46600
- function dot(p, vec3) { // Dot product of a normal in an array against a candidate decoding
46601
- return p[0] * vec3[0] + p[1] * vec3[1] + p[2] * vec3[2];
46602
+ function dot(array, i, vec3) {
46603
+ return array[i] * vec3[0] + array[i + 1] * vec3[1] + array[i + 2] * vec3[2];
46602
46604
  }
46603
46605
 
46604
46606
  const tempMat4$2 = math.mat4();
@@ -64413,7 +64415,7 @@ function convertConstant(gl, constantVal, encoding = null) {
64413
64415
 
64414
64416
  if (p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format) {
64415
64417
  if (encoding === sRGBEncoding) {
64416
- const extension = getExtension$1(gl, 'WEBGL_compressed_texture_s3tc_srgb');
64418
+ const extension = getExtension(gl, 'WEBGL_compressed_texture_s3tc_srgb');
64417
64419
  if (extension !== null) {
64418
64420
  if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT;
64419
64421
  if (p === RGBA_S3TC_DXT1_Format) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
@@ -64423,7 +64425,7 @@ function convertConstant(gl, constantVal, encoding = null) {
64423
64425
  return null;
64424
64426
  }
64425
64427
  } else {
64426
- extension = getExtension$1(gl, 'WEBGL_compressed_texture_s3tc');
64428
+ extension = getExtension(gl, 'WEBGL_compressed_texture_s3tc');
64427
64429
  if (extension !== null) {
64428
64430
  if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
64429
64431
  if (p === RGBA_S3TC_DXT1_Format) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
@@ -64438,7 +64440,7 @@ function convertConstant(gl, constantVal, encoding = null) {
64438
64440
  // PVRTC
64439
64441
 
64440
64442
  if (p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format) {
64441
- const extension = getExtension$1(gl, 'WEBGL_compressed_texture_pvrtc');
64443
+ const extension = getExtension(gl, 'WEBGL_compressed_texture_pvrtc');
64442
64444
  if (extension !== null) {
64443
64445
  if (p === RGB_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
64444
64446
  if (p === RGB_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
@@ -64452,7 +64454,7 @@ function convertConstant(gl, constantVal, encoding = null) {
64452
64454
  // ETC1
64453
64455
 
64454
64456
  if (p === RGB_ETC1_Format) {
64455
- const extension = getExtension$1(gl, 'WEBGL_compressed_texture_etc1');
64457
+ const extension = getExtension(gl, 'WEBGL_compressed_texture_etc1');
64456
64458
  if (extension !== null) {
64457
64459
  return extension.COMPRESSED_RGB_ETC1_WEBGL;
64458
64460
  } else {
@@ -64463,7 +64465,7 @@ function convertConstant(gl, constantVal, encoding = null) {
64463
64465
  // ETC2
64464
64466
 
64465
64467
  if (p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format) {
64466
- const extension = getExtension$1(gl, 'WEBGL_compressed_texture_etc');
64468
+ const extension = getExtension(gl, 'WEBGL_compressed_texture_etc');
64467
64469
  if (extension !== null) {
64468
64470
  if (p === RGB_ETC2_Format) return (encoding === sRGBEncoding) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2;
64469
64471
  if (p === RGBA_ETC2_EAC_Format) return (encoding === sRGBEncoding) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC;
@@ -64479,7 +64481,7 @@ function convertConstant(gl, constantVal, encoding = null) {
64479
64481
  p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
64480
64482
  p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
64481
64483
  p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format) {
64482
- const extension = getExtension$1(gl, 'WEBGL_compressed_texture_astc');
64484
+ const extension = getExtension(gl, 'WEBGL_compressed_texture_astc');
64483
64485
  if (extension !== null) {
64484
64486
  if (p === RGBA_ASTC_4x4_Format) return (encoding === sRGBEncoding) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR;
64485
64487
  if (p === RGBA_ASTC_5x4_Format) return (encoding === sRGBEncoding) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR;
@@ -64503,7 +64505,7 @@ function convertConstant(gl, constantVal, encoding = null) {
64503
64505
  // BPTC
64504
64506
 
64505
64507
  if (p === RGBA_BPTC_Format) {
64506
- const extension = getExtension$1(gl, 'EXT_texture_compression_bptc');
64508
+ const extension = getExtension(gl, 'EXT_texture_compression_bptc');
64507
64509
  if (extension !== null) {
64508
64510
  if (p === RGBA_BPTC_Format) {
64509
64511
  return (encoding === sRGBEncoding) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT;
@@ -64536,9 +64538,6 @@ function convertConstant(gl, constantVal, encoding = null) {
64536
64538
  if (p === LinearMipMapLinearFilter) {
64537
64539
  return gl.LINEAR_MIPMAP_LINEAR;
64538
64540
  }
64539
- if (p === NearestMipMapLinearFilter) {
64540
- return gl.NEAREST_MIPMAP_LINEAR;
64541
- }
64542
64541
  if (p === NearestFilter) {
64543
64542
  return gl.NEAREST;
64544
64543
  }
@@ -64576,7 +64575,7 @@ class Texture2D {
64576
64575
  this.texture = gl.createTexture();
64577
64576
 
64578
64577
  if (preloadColor) {
64579
- this.setPreloadColor(preloadColor || [0, 0, 0, 1]); // Prevents "there is no texture bound to the unit 0" error
64578
+ this.setPreloadColor(preloadColor); // Prevents "there is no texture bound to the unit 0" error
64580
64579
  }
64581
64580
 
64582
64581
  this.allocated = true;
@@ -64595,9 +64594,6 @@ class Texture2D {
64595
64594
  color$2[3] = Math.floor((value[3] !== undefined ? value[3] : 1) * 255);
64596
64595
  }
64597
64596
  const gl = this.gl;
64598
- const glFormat = convertConstant(gl, this.format, this.encoding);
64599
- const glType = convertConstant(gl, this.type);
64600
- const glInternalFormat = getInternalFormat(gl, this.internalFormat, glFormat, glType, this.encoding, false);
64601
64597
  gl.bindTexture(this.target, this.texture);
64602
64598
  if (this.target === gl.TEXTURE_CUBE_MAP) {
64603
64599
  const faces = [
@@ -64609,10 +64605,10 @@ class Texture2D {
64609
64605
  gl.TEXTURE_CUBE_MAP_NEGATIVE_Z
64610
64606
  ];
64611
64607
  for (let i = 0, len = faces.length; i < len; i++) {
64612
- gl.texImage2D(faces[i], 0, glInternalFormat, 1, 1, 0, glFormat, glType, color$2);
64608
+ gl.texImage2D(faces[i], 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, color$2);
64613
64609
  }
64614
64610
  } else {
64615
- gl.texImage2D(this.target, 0, glInternalFormat, 1, 1, 0, glFormat, glType, color$2);
64611
+ gl.texImage2D(this.target, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, color$2);
64616
64612
  }
64617
64613
  gl.bindTexture(this.target, null);
64618
64614
  }
@@ -64772,44 +64768,38 @@ class Texture2D {
64772
64768
  gl.activeTexture(gl.TEXTURE0 + 0);
64773
64769
  gl.bindTexture(this.target, this.texture);
64774
64770
 
64775
- let generateMipMap = false;
64771
+ let supportsMips = mipmaps.length > 1;
64776
64772
 
64777
64773
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this.flipY);
64778
64774
  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha);
64779
64775
  gl.pixelStorei(gl.UNPACK_ALIGNMENT, this.unpackAlignment);
64780
64776
  gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
64781
64777
 
64782
- {
64783
-
64784
- const minFilter = convertConstant(gl, this.minFilter);
64785
- gl.texParameteri(this.target, gl.TEXTURE_MIN_FILTER, minFilter);
64786
- if (minFilter === gl.NEAREST_MIPMAP_NEAREST || minFilter === gl.LINEAR_MIPMAP_NEAREST || minFilter === gl.NEAREST_MIPMAP_LINEAR || minFilter === gl.LINEAR_MIPMAP_LINEAR) {
64787
- generateMipMap = true;
64788
- }
64789
-
64790
- const magFilter = convertConstant(gl, this.magFilter);
64791
- if (magFilter) {
64792
- gl.texParameteri(this.target, gl.TEXTURE_MAG_FILTER, magFilter);
64793
- }
64778
+ const wrapS = convertConstant(gl, this.wrapS);
64779
+ if (wrapS) {
64780
+ gl.texParameteri(this.target, gl.TEXTURE_WRAP_S, wrapS);
64781
+ }
64794
64782
 
64795
- const wrapS = convertConstant(gl, this.wrapS);
64796
- if (wrapS) {
64797
- gl.texParameteri(this.target, gl.TEXTURE_WRAP_S, wrapS);
64798
- }
64783
+ const wrapT = convertConstant(gl, this.wrapT);
64784
+ if (wrapT) {
64785
+ gl.texParameteri(this.target, gl.TEXTURE_WRAP_T, wrapT);
64786
+ }
64799
64787
 
64800
- const wrapT = convertConstant(gl, this.wrapT);
64801
- if (wrapT) {
64802
- gl.texParameteri(this.target, gl.TEXTURE_WRAP_T, wrapT);
64788
+ if (this.type === gl.TEXTURE_3D || this.type === gl.TEXTURE_2D_ARRAY) {
64789
+ const wrapR = convertConstant(gl, this.wrapR);
64790
+ if (wrapR) {
64791
+ gl.texParameteri(this.target, gl.TEXTURE_WRAP_R, wrapR);
64803
64792
  }
64793
+ gl.texParameteri(this.type, gl.TEXTURE_WRAP_R, wrapR);
64794
+ }
64804
64795
 
64805
- if (this.type === gl.TEXTURE_3D || this.type === gl.TEXTURE_2D_ARRAY) {
64806
- const wrapR = convertConstant(gl, this.wrapR);
64807
- if (wrapR) {
64808
- gl.texParameteri(this.target, gl.TEXTURE_WRAP_R, wrapR);
64809
- }
64810
- gl.texParameteri(this.type, gl.TEXTURE_WRAP_R, wrapR);
64811
- }
64796
+ if (supportsMips) {
64797
+ gl.texParameteri(this.target, gl.TEXTURE_MIN_FILTER, filterFallback(gl, this.minFilter));
64798
+ gl.texParameteri(this.target, gl.TEXTURE_MAG_FILTER, filterFallback(gl, this.magFilter));
64812
64799
 
64800
+ } else {
64801
+ gl.texParameteri(this.target, gl.TEXTURE_MIN_FILTER, convertConstant(gl, this.minFilter));
64802
+ gl.texParameteri(this.target, gl.TEXTURE_MAG_FILTER, convertConstant(gl, this.magFilter));
64813
64803
  }
64814
64804
 
64815
64805
  const glFormat = convertConstant(gl, this.format, this.encoding);
@@ -64829,13 +64819,13 @@ class Texture2D {
64829
64819
  console.warn('Attempt to load unsupported compressed texture format in .setCompressedData()');
64830
64820
  }
64831
64821
  } else {
64832
- gl.texSubImage2D(gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data);
64822
+ gl.texSubImage2D(gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data);
64833
64823
  }
64834
64824
  }
64835
64825
 
64836
- if (generateMipMap) {
64837
- gl.generateMipmap(this.target);
64838
- }
64826
+ // if (generateMipMap) {
64827
+ // // gl.generateMipmap(this.target); // Only for roughness textures?
64828
+ // }
64839
64829
 
64840
64830
  gl.bindTexture(this.target, null);
64841
64831
  }
@@ -64962,6 +64952,14 @@ function getInternalFormat(gl, internalFormatName, glFormat, glType, encoding, i
64962
64952
  return internalFormat;
64963
64953
  }
64964
64954
 
64955
+ function filterFallback(gl, f) {
64956
+ if (f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter) {
64957
+ return gl.NEAREST;
64958
+ }
64959
+ return gl.LINEAR;
64960
+
64961
+ }
64962
+
64965
64963
  /**
64966
64964
  * Instantiated by VBOSceneModel#createTexture
64967
64965
  *
@@ -65882,6 +65880,1059 @@ class SceneModel {
65882
65880
  }
65883
65881
  }
65884
65882
 
65883
+ class LoadingManager {
65884
+
65885
+ constructor(onLoad, onProgress, onError) {
65886
+
65887
+ this.isLoading = false;
65888
+ this.itemsLoaded = 0;
65889
+ this.itemsTotal = 0;
65890
+ this.urlModifier = undefined;
65891
+ this.handlers = [];
65892
+
65893
+ this.onStart = undefined;
65894
+ this.onLoad = onLoad;
65895
+ this.onProgress = onProgress;
65896
+ this.onError = onError;
65897
+ }
65898
+
65899
+ itemStart(url) {
65900
+ this.itemsTotal++;
65901
+ if (this.isLoading === false) {
65902
+ if (this.onStart !== undefined) {
65903
+ this.onStart(url, this.itemsLoaded, this.itemsTotal);
65904
+ }
65905
+ }
65906
+ this.isLoading = true;
65907
+ }
65908
+
65909
+ itemEnd(url) {
65910
+ this.itemsLoaded++;
65911
+ if (this.onProgress !== undefined) {
65912
+ this.onProgress(url, this.itemsLoaded, this.itemsTotal);
65913
+ }
65914
+ if (this.itemsLoaded === this.itemsTotal) {
65915
+ this.isLoading = false;
65916
+ if (this.onLoad !== undefined) {
65917
+ this.onLoad();
65918
+ }
65919
+ }
65920
+ }
65921
+
65922
+ itemError(url) {
65923
+ if (this.onError !== undefined) {
65924
+ this.onError(url);
65925
+ }
65926
+ }
65927
+
65928
+ resolveURL(url) {
65929
+ if (this.urlModifier) {
65930
+ return this.urlModifier(url);
65931
+ }
65932
+ return url;
65933
+ }
65934
+
65935
+ setURLModifier(transform) {
65936
+ this.urlModifier = transform;
65937
+ return this;
65938
+ }
65939
+
65940
+ addHandler(regex, loader) {
65941
+ this.handlers.push(regex, loader);
65942
+ return this;
65943
+ }
65944
+
65945
+ removeHandler(regex) {
65946
+ const index = this.handlers.indexOf(regex);
65947
+ if (index !== -1) {
65948
+ this.handlers.splice(index, 2);
65949
+ }
65950
+ return this;
65951
+ }
65952
+
65953
+ getHandler(file) {
65954
+ for (let i = 0, l = this.handlers.length; i < l; i += 2) {
65955
+ const regex = this.handlers[i];
65956
+ const loader = this.handlers[i + 1];
65957
+ if (regex.global) regex.lastIndex = 0; // see #17920
65958
+ if (regex.test(file)) {
65959
+ return loader;
65960
+ }
65961
+ }
65962
+ return null;
65963
+ }
65964
+ }
65965
+
65966
+ const DefaultLoadingManager = new LoadingManager();
65967
+
65968
+ class Loader {
65969
+
65970
+ constructor(manager) {
65971
+
65972
+ this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
65973
+
65974
+ this.crossOrigin = 'anonymous';
65975
+ this.withCredentials = false;
65976
+ this.path = '';
65977
+ this.resourcePath = '';
65978
+ this.requestHeader = {};
65979
+ }
65980
+
65981
+ load( /* url, onLoad, onProgress, onError */) {
65982
+ }
65983
+
65984
+ loadAsync(url, onProgress) {
65985
+ const scope = this;
65986
+ return new Promise(function (resolve, reject) {
65987
+ scope.load(url, resolve, onProgress, reject);
65988
+ });
65989
+ }
65990
+
65991
+ parse( /* data */) {
65992
+ }
65993
+
65994
+ setCrossOrigin(crossOrigin) {
65995
+ this.crossOrigin = crossOrigin;
65996
+ return this;
65997
+ }
65998
+
65999
+ setWithCredentials(value) {
66000
+ this.withCredentials = value;
66001
+ return this;
66002
+ }
66003
+
66004
+ setPath(path) {
66005
+ this.path = path;
66006
+ return this;
66007
+ }
66008
+
66009
+ setResourcePath(resourcePath) {
66010
+ this.resourcePath = resourcePath;
66011
+ return this;
66012
+ }
66013
+
66014
+ setRequestHeader(requestHeader) {
66015
+ this.requestHeader = requestHeader;
66016
+ return this;
66017
+ }
66018
+ }
66019
+
66020
+ /**
66021
+ * @author Deepkolos / https://github.com/deepkolos
66022
+ */
66023
+
66024
+ class WorkerPool$1 {
66025
+
66026
+ constructor(pool = 4) {
66027
+ this.pool = pool;
66028
+ this.queue = [];
66029
+ this.workers = [];
66030
+ this.workersResolve = [];
66031
+ this.workerStatus = 0;
66032
+ }
66033
+
66034
+ _initWorker(workerId) {
66035
+ if (!this.workers[workerId]) {
66036
+ const worker = this.workerCreator();
66037
+ worker.addEventListener('message', this._onMessage.bind(this, workerId));
66038
+ this.workers[workerId] = worker;
66039
+ }
66040
+ }
66041
+
66042
+ _getIdleWorker() {
66043
+ for (let i = 0; i < this.pool; i++)
66044
+ if (!(this.workerStatus & (1 << i))) return i;
66045
+ return -1;
66046
+ }
66047
+
66048
+ _onMessage(workerId, msg) {
66049
+ const resolve = this.workersResolve[workerId];
66050
+ resolve && resolve(msg);
66051
+ if (this.queue.length) {
66052
+ const {resolve, msg, transfer} = this.queue.shift();
66053
+ this.workersResolve[workerId] = resolve;
66054
+ this.workers[workerId].postMessage(msg, transfer);
66055
+ } else {
66056
+ this.workerStatus ^= 1 << workerId;
66057
+ }
66058
+ }
66059
+
66060
+ setWorkerCreator(workerCreator) {
66061
+ this.workerCreator = workerCreator;
66062
+ }
66063
+
66064
+ setWorkerLimit(pool) {
66065
+ this.pool = pool;
66066
+ }
66067
+
66068
+ postMessage(msg, transfer) {
66069
+ return new Promise((resolve) => {
66070
+ const workerId = this._getIdleWorker();
66071
+ if (workerId !== -1) {
66072
+ this._initWorker(workerId);
66073
+ this.workerStatus |= 1 << workerId;
66074
+ this.workersResolve[workerId] = resolve;
66075
+ this.workers[workerId].postMessage(msg, transfer);
66076
+ } else {
66077
+ this.queue.push({resolve, msg, transfer});
66078
+ }
66079
+ });
66080
+ }
66081
+
66082
+ destroy() {
66083
+
66084
+ this.workers.forEach((worker) => worker.terminate());
66085
+ this.workersResolve.length = 0;
66086
+ this.workers.length = 0;
66087
+ this.queue.length = 0;
66088
+ this.workerStatus = 0;
66089
+
66090
+ }
66091
+
66092
+ }
66093
+
66094
+ /**
66095
+ * Transcodes texture data.
66096
+ *
66097
+ * A {@link SceneModel} configured with an appropriate TextureTranscoder will allow us to add textures from
66098
+ * transcoded buffers or files. For a concrete example, see {@link VBOSceneModel}, which can be configured with
66099
+ * a {@link KTX2TextureTranscoder}, which allows us to add textures from KTX2 buffers and files.
66100
+ *
66101
+ * @interface
66102
+ */
66103
+ class TextureTranscoder {
66104
+
66105
+ /**
66106
+ * Transcodes texture data from transcoded buffers into a {@link Texture2D}.
66107
+ *
66108
+ * @param {ArrayBuffer[]} buffers Transcoded texture data. Given as an array of buffers so that we can support
66109
+ * multi-image textures, such as cube maps.
66110
+ * @param {*} config Transcoding options.
66111
+ * @param {Texture2D} texture The texture to load.
66112
+ * @returns {Promise} Resolves when the texture has loaded.
66113
+ */
66114
+ transcode(buffers, texture, config = {}) {
66115
+ }
66116
+
66117
+ /**
66118
+ * Destroys this transcoder.
66119
+ */
66120
+ destroy() {
66121
+ }
66122
+ }
66123
+
66124
+ const Cache = {
66125
+
66126
+ enabled: false,
66127
+ files: {},
66128
+
66129
+ add: function (key, file) {
66130
+ if (this.enabled === false) {
66131
+ return;
66132
+ }
66133
+ this.files[key] = file;
66134
+ },
66135
+
66136
+ get: function (key) {
66137
+ if (this.enabled === false) {
66138
+ return;
66139
+ }
66140
+ return this.files[key];
66141
+ },
66142
+
66143
+ remove: function (key) {
66144
+ delete this.files[key];
66145
+ },
66146
+
66147
+ clear: function () {
66148
+ this.files = {};
66149
+ }
66150
+ };
66151
+
66152
+ const loading = {};
66153
+
66154
+ class FileLoader extends Loader {
66155
+
66156
+ constructor(manager) {
66157
+ super(manager);
66158
+ }
66159
+
66160
+ load(url, onLoad, onProgress, onError) {
66161
+ if (url === undefined) {
66162
+ url = '';
66163
+ }
66164
+ if (this.path !== undefined) {
66165
+ url = this.path + url;
66166
+ }
66167
+ url = this.manager.resolveURL(url);
66168
+ const cached = Cache.get(url);
66169
+ if (cached !== undefined) {
66170
+ this.manager.itemStart(url);
66171
+ setTimeout(() => {
66172
+ if (onLoad) {
66173
+ onLoad(cached);
66174
+ }
66175
+ this.manager.itemEnd(url);
66176
+ }, 0);
66177
+ return cached;
66178
+ }
66179
+ if (loading[url] !== undefined) {
66180
+ loading[url].push({onLoad, onProgress, onError});
66181
+ return;
66182
+ }
66183
+ loading[url] = [];
66184
+ loading[url].push({onLoad, onProgress, onError});
66185
+ const req = new Request(url, {
66186
+ headers: new Headers(this.requestHeader),
66187
+ credentials: this.withCredentials ? 'include' : 'same-origin'
66188
+ });
66189
+ const mimeType = this.mimeType;
66190
+ const responseType = this.responseType;
66191
+ fetch(req).then(response => {
66192
+ if (response.status === 200 || response.status === 0) {
66193
+ // Some browsers return HTTP Status 0 when using non-http protocol
66194
+ // e.g. 'file://' or 'data://'. Handle as success.
66195
+ if (response.status === 0) {
66196
+ console.warn('FileLoader: HTTP Status 0 received.');
66197
+ }
66198
+ if (typeof ReadableStream === 'undefined' || response.body.getReader === undefined) {
66199
+ return response;
66200
+ }
66201
+ const callbacks = loading[url];
66202
+ const reader = response.body.getReader();
66203
+ const contentLength = response.headers.get('Content-Length');
66204
+ const total = contentLength ? parseInt(contentLength) : 0;
66205
+ const lengthComputable = total !== 0;
66206
+ let loaded = 0;
66207
+ const stream = new ReadableStream({
66208
+ start(controller) {
66209
+ readData();
66210
+
66211
+ function readData() {
66212
+ reader.read().then(({done, value}) => {
66213
+ if (done) {
66214
+ controller.close();
66215
+ } else {
66216
+ loaded += value.byteLength;
66217
+ const event = new ProgressEvent('progress', {lengthComputable, loaded, total});
66218
+ for (let i = 0, il = callbacks.length; i < il; i++) {
66219
+ const callback = callbacks[i];
66220
+ if (callback.onProgress) {
66221
+ callback.onProgress(event);
66222
+ }
66223
+ }
66224
+ controller.enqueue(value);
66225
+ readData();
66226
+ }
66227
+ });
66228
+ }
66229
+ }
66230
+ });
66231
+ return new Response(stream);
66232
+ } else {
66233
+ throw Error(`fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`);
66234
+ }
66235
+ }).then(response => {
66236
+ switch (responseType) {
66237
+ case 'arraybuffer':
66238
+ return response.arrayBuffer();
66239
+ case 'blob':
66240
+ return response.blob();
66241
+ case 'document':
66242
+ return response.text()
66243
+ .then(text => {
66244
+ const parser = new DOMParser();
66245
+ return parser.parseFromString(text, mimeType);
66246
+ });
66247
+ case 'json':
66248
+ return response.json();
66249
+ default:
66250
+ if (mimeType === undefined) {
66251
+ return response.text();
66252
+ } else {
66253
+ // sniff encoding
66254
+ const re = /charset="?([^;"\s]*)"?/i;
66255
+ const exec = re.exec(mimeType);
66256
+ const label = exec && exec[1] ? exec[1].toLowerCase() : undefined;
66257
+ const decoder = new TextDecoder(label);
66258
+ return response.arrayBuffer().then(ab => decoder.decode(ab));
66259
+ }
66260
+ }
66261
+ }).then(data => {
66262
+ // Add to cache only on HTTP success, so that we do not cache
66263
+ // error response bodies as proper responses to requests.
66264
+ Cache.add(url, data);
66265
+ const callbacks = loading[url];
66266
+ delete loading[url];
66267
+ for (let i = 0, il = callbacks.length; i < il; i++) {
66268
+ const callback = callbacks[i];
66269
+ if (callback.onLoad) {
66270
+ callback.onLoad(data);
66271
+ }
66272
+ }
66273
+ }).catch(err => {
66274
+ // Abort errors and other errors are handled the same
66275
+ const callbacks = loading[url];
66276
+ if (callbacks === undefined) {
66277
+ // When onLoad was called and url was deleted in `loading`
66278
+ this.manager.itemError(url);
66279
+ throw err;
66280
+
66281
+ }
66282
+ delete loading[url];
66283
+ for (let i = 0, il = callbacks.length; i < il; i++) {
66284
+ const callback = callbacks[i];
66285
+ if (callback.onError) {
66286
+ callback.onError(err);
66287
+ }
66288
+ }
66289
+ this.manager.itemError(url);
66290
+ }).finally(() => {
66291
+ this.manager.itemEnd(url);
66292
+ });
66293
+ this.manager.itemStart(url);
66294
+ }
66295
+
66296
+ setResponseType(value) {
66297
+ this.responseType = value;
66298
+ return this;
66299
+ }
66300
+
66301
+ setMimeType(value) {
66302
+ this.mimeType = value;
66303
+ return this;
66304
+ }
66305
+ }
66306
+
66307
+ const KTX2TransferSRGB = 2;
66308
+ const KTX2_ALPHA_PREMULTIPLIED = 1;
66309
+
66310
+ let activeTranscoders = 0;
66311
+
66312
+ /**
66313
+ * Transcodes texture data from KTX2.
66314
+ *
66315
+ * ## Overview
66316
+ *
66317
+ * * Uses the [Basis Universal GPU Texture Codec](https://github.com/BinomialLLC/basis_universal) to
66318
+ * transcode [KTX2](https://github.khronos.org/KTX-Specification/) textures.
66319
+ * * {@link XKTLoaderPlugin} uses a KTX2TextureTranscoder to load textures in XKT files.
66320
+ * * {@link VBOSceneModel} uses a KTX2TextureTranscoder to enable us to add KTX2-encoded textures.
66321
+ * * Loads the Basis Codec from [CDN](https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/) by default, but can
66322
+ * also be configured to load the Codec from local files.
66323
+ * * We also bundle the Basis Codec with the xeokit-sdk npm package, and in the [repository](https://github.com/xeokit/xeokit-sdk/tree/master/dist/basis).
66324
+ *
66325
+ * ## What is KTX2?
66326
+ *
66327
+ * A [KTX2](https://github.khronos.org/KTX-Specification/) file stores GPU texture data in the Khronos Texture 2.0 (KTX2) container format. It contains image data for
66328
+ * a texture asset compressed with Basis Universal (BasisU) supercompression that can be transcoded to different formats
66329
+ * depending on the support provided by the target devices. KTX2 provides a lightweight format for distributing texture
66330
+ * assets to GPUs. Due to BasisU compression, KTX2 files can store any image format supported by GPUs.
66331
+ *
66332
+ * ## Loading XKT files containing KTX2 textures
66333
+ *
66334
+ * {@link XKTLoaderPlugin} uses a KTX2TextureTranscoder to load textures in XKT files. An XKTLoaderPlugin has its own
66335
+ * default KTX2TextureTranscoder, configured to load the Basis Codec from the [CDN](https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/). If we wish, we can override that with our own
66336
+ * KTX2TextureTranscoder, configured to load the Codec locally.
66337
+ *
66338
+ * In the example below, we'll create a {@link Viewer} and add an {@link XKTLoaderPlugin}
66339
+ * configured with a KTX2TextureTranscoder. Then we'll use the XKTLoaderPlugin to load an
66340
+ * XKT file that contains KTX2 textures, which the plugin will transcode using
66341
+ * its KTX2TextureTranscoder.
66342
+ *
66343
+ * We'll configure our KTX2TextureTranscoder to load the Basis Codec from a local directory. If we were happy with loading the
66344
+ * Codec from our [CDN](https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/) (ie. our app will always have an Internet connection) then we could just leave out the
66345
+ * KTX2TextureTranscoder altogether, and let the XKTLoaderPlugin use its internal default KTX2TextureTranscoder, which is configured to
66346
+ * load the Codec from the CDN. We'll stick with loading our own Codec, in case we want to run our app without an Internet connection.
66347
+ *
66348
+ * <a href="https://xeokit.github.io/xeokit-sdk/examples/#loading_XKT_Textures_HousePlan"><img src="https://xeokit.github.io/xeokit-sdk/assets/images/xktWithTextures.png"></a>
66349
+ *
66350
+ * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XKT_Textures_HousePlan)]
66351
+ *
66352
+ * ````javascript
66353
+ * const viewer = new Viewer({
66354
+ * canvasId: "myCanvas",
66355
+ * transparent: true
66356
+ * });
66357
+ *
66358
+ * viewer.camera.eye = [-2.56, 8.38, 8.27];
66359
+ * viewer.camera.look = [13.44, 3.31, -14.83];
66360
+ * viewer.camera.up = [0.10, 0.98, -0.14];
66361
+ *
66362
+ * const textureTranscoder = new KTX2TextureTranscoder({
66363
+ * viewer,
66364
+ * transcoderPath: "./../dist/basis/" // <------ Path to Basis Universal transcoder
66365
+ * });
66366
+ *
66367
+ * const xktLoader = new XKTLoaderPlugin(viewer, {
66368
+ * textureTranscoder // <<------------- Transcodes KTX2 textures in XKT files
66369
+ * });
66370
+ *
66371
+ * const sceneModel = xktLoader.load({
66372
+ * id: "myModel",
66373
+ * src: "./HousePlan.xkt" // <<------ XKT file with KTX2 textures
66374
+ * });
66375
+ * ````
66376
+ *
66377
+ * ## Loading KTX2 files into a VBOSceneModel
66378
+ *
66379
+ * A {@link SceneModel} that is configured with a KTX2TextureTranscoder will
66380
+ * allow us to load textures into it from KTX2-transcoded buffers or files.
66381
+ *
66382
+ * In the example below, we'll create a {@link Viewer}, containing a {@link VBOSceneModel} configured with a
66383
+ * KTX2TextureTranscoder.
66384
+ *
66385
+ * We'll then programmatically create a simple object within the VBOSceneModel, consisting of
66386
+ * a single box mesh with a texture loaded from a KTX2 file, which our VBOSceneModel internally transcodes, using
66387
+ * its KTX2TextureTranscoder.
66388
+ *
66389
+ * As in the previous example, we'll configure our KTX2TextureTranscoder to load the Basis Codec from a local directory.
66390
+ *
66391
+ * * [Run a similar example](http://localhost:8080/examples/sceneRepresentation_VBOSceneModel_batching_textures_ktx2.html)
66392
+ *
66393
+ * ````javascript
66394
+ * const viewer = new Viewer({
66395
+ * canvasId: "myCanvas",
66396
+ * transparent: true
66397
+ * });
66398
+ *
66399
+ * viewer.scene.camera.eye = [-21.80, 4.01, 6.56];
66400
+ * viewer.scene.camera.look = [0, -5.75, 0];
66401
+ * viewer.scene.camera.up = [0.37, 0.91, -0.11];
66402
+ *
66403
+ * const textureTranscoder = new KTX2TextureTranscoder({
66404
+ * viewer,
66405
+ * transcoderPath: "./../dist/basis/" // <------ Path to BasisU transcoder module
66406
+ * });
66407
+ *
66408
+ * const vboSceneModel = new VBOSceneModel(viewer.scene, {
66409
+ * id: "myModel",
66410
+ * textureTranscoder // <<-------------------- Configure model with our transcoder
66411
+ * });
66412
+ *
66413
+ * vboSceneModel.createTexture({
66414
+ * id: "myColorTexture",
66415
+ * src: "../assets/textures/compressed/sample_uastc_zstd.ktx2" // <<----- KTX2 texture asset
66416
+ * });
66417
+ *
66418
+ * vboSceneModel.createTexture({
66419
+ * id: "myMetallicRoughnessTexture",
66420
+ * src: "../assets/textures/alpha/crosshatchAlphaMap.jpg" // <<----- JPEG texture asset
66421
+ * });
66422
+ *
66423
+ * vboSceneModel.createTextureSet({
66424
+ * id: "myTextureSet",
66425
+ * colorTextureId: "myColorTexture",
66426
+ * metallicRoughnessTextureId: "myMetallicRoughnessTexture"
66427
+ * });
66428
+ *
66429
+ * vboSceneModel.createMesh({
66430
+ * id: "myMesh",
66431
+ * textureSetId: "myTextureSet",
66432
+ * primitive: "triangles",
66433
+ * positions: [1, 1, 1, ...],
66434
+ * normals: [0, 0, 1, 0, ...],
66435
+ * uv: [1, 0, 0, ...],
66436
+ * indices: [0, 1, 2, ...],
66437
+ * });
66438
+ *
66439
+ * vboSceneModel.createEntity({
66440
+ * id: "myEntity",
66441
+ * meshIds: ["myMesh"]
66442
+ * });
66443
+ *
66444
+ * vboSceneModel.finalize();
66445
+ * ````
66446
+ *
66447
+ * ## Loading KTX2 ArrayBuffers into a VBOSceneModel
66448
+ *
66449
+ * A {@link SceneModel} that is configured with a KTX2TextureTranscoder will also allow us to load textures into
66450
+ * it from KTX2 ArrayBuffers.
66451
+ *
66452
+ * In the example below, we'll create a {@link Viewer}, containing a {@link VBOSceneModel} configured with a
66453
+ * KTX2TextureTranscoder.
66454
+ *
66455
+ * We'll then programmatically create a simple object within the VBOSceneModel, consisting of
66456
+ * a single mesh with a texture loaded from a KTX2 ArrayBuffer, which our VBOSceneModel internally transcodes, using
66457
+ * its KTX2TextureTranscoder.
66458
+ *
66459
+ * ````javascript
66460
+ * const viewer = new Viewer({
66461
+ * canvasId: "myCanvas",
66462
+ * transparent: true
66463
+ * });
66464
+ *
66465
+ * viewer.scene.camera.eye = [-21.80, 4.01, 6.56];
66466
+ * viewer.scene.camera.look = [0, -5.75, 0];
66467
+ * viewer.scene.camera.up = [0.37, 0.91, -0.11];
66468
+ *
66469
+ * const textureTranscoder = new KTX2TextureTranscoder({
66470
+ * viewer,
66471
+ * transcoderPath: "./../dist/basis/" // <------ Path to BasisU transcoder module
66472
+ * });
66473
+ *
66474
+ * const vboSceneModel = new VBOSceneModel(viewer.scene, {
66475
+ * id: "myModel",
66476
+ * textureTranscoder // <<-------------------- Configure model with our transcoder
66477
+ * });
66478
+ *
66479
+ * utils.loadArraybuffer("../assets/textures/compressed/sample_uastc_zstd.ktx2",(arrayBuffer) => {
66480
+ *
66481
+ * vboSceneModel.createTexture({
66482
+ * id: "myColorTexture",
66483
+ * buffers: [arrayBuffer] // <<----- KTX2 texture asset
66484
+ * });
66485
+ *
66486
+ * vboSceneModel.createTexture({
66487
+ * id: "myMetallicRoughnessTexture",
66488
+ * src: "../assets/textures/alpha/crosshatchAlphaMap.jpg" // <<----- JPEG texture asset
66489
+ * });
66490
+ *
66491
+ * vboSceneModel.createTextureSet({
66492
+ * id: "myTextureSet",
66493
+ * colorTextureId: "myColorTexture",
66494
+ * metallicRoughnessTextureId: "myMetallicRoughnessTexture"
66495
+ * });
66496
+ *
66497
+ * vboSceneModel.createMesh({
66498
+ * id: "myMesh",
66499
+ * textureSetId: "myTextureSet",
66500
+ * primitive: "triangles",
66501
+ * positions: [1, 1, 1, ...],
66502
+ * normals: [0, 0, 1, 0, ...],
66503
+ * uv: [1, 0, 0, ...],
66504
+ * indices: [0, 1, 2, ...],
66505
+ * });
66506
+ *
66507
+ * vboSceneModel.createEntity({
66508
+ * id: "myEntity",
66509
+ * meshIds: ["myMesh"]
66510
+ * });
66511
+ *
66512
+ * vboSceneModel.finalize();
66513
+ * });
66514
+ * ````
66515
+ *
66516
+ * @implements {TextureTranscoder}
66517
+ */
66518
+ class KTX2TextureTranscoder {
66519
+
66520
+ /**
66521
+ * Creates a new KTX2TextureTranscoder.
66522
+ *
66523
+ * @param {Viewer} viewer The Viewer that our KTX2TextureTranscoder will be used with. This KTX2TextureTranscoder
66524
+ * must only be used to transcode textures for this Viewer. This is because the Viewer's capabilities will decide
66525
+ * what target GPU formats this KTX2TextureTranscoder will transcode to.
66526
+ * @param {String} [transcoderPath="https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/"] Path to the Basis
66527
+ * transcoder module that internally does the heavy lifting for our KTX2TextureTranscoder. If we omit this configuration,
66528
+ * then our KTX2TextureTranscoder will load it from ````https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/```` by
66529
+ * default. Therefore, make sure your application is connected to the internet if you wish to use the default transcoder path.
66530
+ * @param {Number} [workerLimit] The maximum number of Workers to use for transcoding.
66531
+ */
66532
+ constructor({viewer, transcoderPath, workerLimit}) {
66533
+
66534
+ this._transcoderPath = transcoderPath || "https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/";
66535
+ this._transcoderBinary = null;
66536
+ this._transcoderPending = null;
66537
+ this._workerPool = new WorkerPool$1();
66538
+ this._workerSourceURL = '';
66539
+
66540
+ if (workerLimit) {
66541
+ this._workerPool.setWorkerLimit(workerLimit);
66542
+ }
66543
+
66544
+ const viewerCapabilities = viewer.capabilities;
66545
+
66546
+ this._workerConfig = {
66547
+ astcSupported: viewerCapabilities.astcSupported,
66548
+ etc1Supported: viewerCapabilities.etc1Supported,
66549
+ etc2Supported: viewerCapabilities.etc2Supported,
66550
+ dxtSupported: viewerCapabilities.dxtSupported,
66551
+ bptcSupported: viewerCapabilities.bptcSupported,
66552
+ pvrtcSupported: viewerCapabilities.pvrtcSupported
66553
+ };
66554
+
66555
+ this._supportedFileTypes = ["xkt2"];
66556
+ }
66557
+
66558
+ _init() {
66559
+ if (!this._transcoderPending) {
66560
+ const jsLoader = new FileLoader();
66561
+ jsLoader.setPath(this._transcoderPath);
66562
+ jsLoader.setWithCredentials(this.withCredentials);
66563
+ const jsContent = jsLoader.loadAsync('basis_transcoder.js');
66564
+ const binaryLoader = new FileLoader();
66565
+ binaryLoader.setPath(this._transcoderPath);
66566
+ binaryLoader.setResponseType('arraybuffer');
66567
+ binaryLoader.setWithCredentials(this.withCredentials);
66568
+ const binaryContent = binaryLoader.loadAsync('basis_transcoder.wasm');
66569
+ this._transcoderPending = Promise.all([jsContent, binaryContent])
66570
+ .then(([jsContent, binaryContent]) => {
66571
+ const fn = KTX2TextureTranscoder.BasisWorker.toString();
66572
+ const body = [
66573
+ '/* constants */',
66574
+ 'let _EngineFormat = ' + JSON.stringify(KTX2TextureTranscoder.EngineFormat),
66575
+ 'let _TranscoderFormat = ' + JSON.stringify(KTX2TextureTranscoder.TranscoderFormat),
66576
+ 'let _BasisFormat = ' + JSON.stringify(KTX2TextureTranscoder.BasisFormat),
66577
+ '/* basis_transcoder.js */',
66578
+ jsContent,
66579
+ '/* worker */',
66580
+ fn.substring(fn.indexOf('{') + 1, fn.lastIndexOf('}'))
66581
+ ].join('\n');
66582
+ this._workerSourceURL = URL.createObjectURL(new Blob([body]));
66583
+ this._transcoderBinary = binaryContent;
66584
+ this._workerPool.setWorkerCreator(() => {
66585
+ const worker = new Worker(this._workerSourceURL);
66586
+ const transcoderBinary = this._transcoderBinary.slice(0);
66587
+ worker.postMessage({
66588
+ type: 'init',
66589
+ config: this._workerConfig,
66590
+ transcoderBinary
66591
+ }, [transcoderBinary]);
66592
+ return worker;
66593
+ });
66594
+ });
66595
+ if (activeTranscoders > 0) {
66596
+ console.warn('KTX2TextureTranscoder: Multiple active KTX2TextureTranscoder may cause performance issues.' + ' Use a single KTX2TextureTranscoder instance, or call .dispose() on old instances.');
66597
+ }
66598
+ activeTranscoders++;
66599
+ }
66600
+ return this._transcoderPending;
66601
+ }
66602
+
66603
+ /**
66604
+ * Transcodes texture data from transcoded buffers into a {@link Texture2D}.
66605
+ *
66606
+ * @param {ArrayBuffer[]} buffers Transcoded texture data. Given as an array of buffers so that we can support multi-image textures, such as cube maps.
66607
+ * @param {*} config Transcoding options.
66608
+ * @param {Texture2D} texture The texture to load.
66609
+ * @returns {Promise} Resolves when the texture has loaded.
66610
+ */
66611
+ transcode(buffers, texture, config = {}) {
66612
+ return new Promise((resolve, reject) => {
66613
+ const taskConfig = config;
66614
+ this._init().then(() => {
66615
+ return this._workerPool.postMessage({
66616
+ type: 'transcode',
66617
+ buffers,
66618
+ taskConfig: taskConfig
66619
+ }, buffers);
66620
+ }).then((e) => {
66621
+ const transcodeResult = e.data;
66622
+ const {mipmaps, width, height, format, type, error, dfdTransferFn, dfdFlags} = transcodeResult;
66623
+ if (type === 'error') {
66624
+ return reject(error);
66625
+ }
66626
+ texture.setCompressedData({
66627
+ mipmaps,
66628
+ props: {
66629
+ format: format,
66630
+ minFilter: mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter,
66631
+ magFilter: mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter,
66632
+ encoding: dfdTransferFn === KTX2TransferSRGB ? sRGBEncoding : LinearEncoding,
66633
+ premultiplyAlpha: !!(dfdFlags & KTX2_ALPHA_PREMULTIPLIED)
66634
+ }
66635
+ });
66636
+ resolve();
66637
+ });
66638
+ });
66639
+ }
66640
+
66641
+ /**
66642
+ * Destroys this KTX2TextureTranscoder
66643
+ */
66644
+ destroy() {
66645
+ URL.revokeObjectURL(this._workerSourceURL);
66646
+ this._workerPool.destroy();
66647
+ activeTranscoders--;
66648
+ }
66649
+ }
66650
+
66651
+ /**
66652
+ * @private
66653
+ */
66654
+ KTX2TextureTranscoder.BasisFormat = {
66655
+ ETC1S: 0,
66656
+ UASTC_4x4: 1
66657
+ };
66658
+
66659
+ /**
66660
+ * @private
66661
+ */
66662
+ KTX2TextureTranscoder.TranscoderFormat = {
66663
+ ETC1: 0,
66664
+ ETC2: 1,
66665
+ BC1: 2,
66666
+ BC3: 3,
66667
+ BC4: 4,
66668
+ BC5: 5,
66669
+ BC7_M6_OPAQUE_ONLY: 6,
66670
+ BC7_M5: 7,
66671
+ PVRTC1_4_RGB: 8,
66672
+ PVRTC1_4_RGBA: 9,
66673
+ ASTC_4x4: 10,
66674
+ ATC_RGB: 11,
66675
+ ATC_RGBA_INTERPOLATED_ALPHA: 12,
66676
+ RGBA32: 13,
66677
+ RGB565: 14,
66678
+ BGR565: 15,
66679
+ RGBA4444: 16
66680
+ };
66681
+
66682
+ /**
66683
+ * @private
66684
+ */
66685
+ KTX2TextureTranscoder.EngineFormat = {
66686
+ RGBAFormat: RGBAFormat,
66687
+ RGBA_ASTC_4x4_Format: RGBA_ASTC_4x4_Format,
66688
+ RGBA_BPTC_Format: RGBA_BPTC_Format,
66689
+ RGBA_ETC2_EAC_Format: RGBA_ETC2_EAC_Format,
66690
+ RGBA_PVRTC_4BPPV1_Format: RGBA_PVRTC_4BPPV1_Format,
66691
+ RGBA_S3TC_DXT5_Format: RGBA_S3TC_DXT5_Format,
66692
+ RGB_ETC1_Format: RGB_ETC1_Format,
66693
+ RGB_ETC2_Format: RGB_ETC2_Format,
66694
+ RGB_PVRTC_4BPPV1_Format: RGB_PVRTC_4BPPV1_Format,
66695
+ RGB_S3TC_DXT1_Format: RGB_S3TC_DXT1_Format
66696
+ };
66697
+
66698
+ /* WEB WORKER */
66699
+
66700
+ /**
66701
+ * @private
66702
+ * @constructor
66703
+ */
66704
+ KTX2TextureTranscoder.BasisWorker = function () {
66705
+
66706
+ let config;
66707
+ let transcoderPending;
66708
+ let BasisModule;
66709
+
66710
+ const EngineFormat = _EngineFormat; // eslint-disable-line no-undef
66711
+ const TranscoderFormat = _TranscoderFormat; // eslint-disable-line no-undef
66712
+ const BasisFormat = _BasisFormat; // eslint-disable-line no-undef
66713
+
66714
+ self.addEventListener('message', function (e) {
66715
+ const message = e.data;
66716
+ switch (message.type) {
66717
+ case 'init':
66718
+ config = message.config;
66719
+ init(message.transcoderBinary);
66720
+ break;
66721
+ case 'transcode':
66722
+ transcoderPending.then(() => {
66723
+ try {
66724
+ const {
66725
+ width,
66726
+ height,
66727
+ hasAlpha,
66728
+ mipmaps,
66729
+ format,
66730
+ dfdTransferFn,
66731
+ dfdFlags
66732
+ } = transcode(message.buffers[0]);
66733
+ const buffers = [];
66734
+ for (let i = 0; i < mipmaps.length; ++i) {
66735
+ buffers.push(mipmaps[i].data.buffer);
66736
+ }
66737
+ self.postMessage({
66738
+ type: 'transcode',
66739
+ id: message.id,
66740
+ width,
66741
+ height,
66742
+ hasAlpha,
66743
+ mipmaps,
66744
+ format,
66745
+ dfdTransferFn,
66746
+ dfdFlags
66747
+ }, buffers);
66748
+ } catch (error) {
66749
+ console.error(`[KTX2TextureTranscoder.BasisWorker]: ${error}`);
66750
+ self.postMessage({type: 'error', id: message.id, error: error.message});
66751
+ }
66752
+ });
66753
+ break;
66754
+ }
66755
+ });
66756
+
66757
+ function init(wasmBinary) {
66758
+ transcoderPending = new Promise(resolve => {
66759
+ BasisModule = {
66760
+ wasmBinary,
66761
+ onRuntimeInitialized: resolve
66762
+ };
66763
+ BASIS(BasisModule); // eslint-disable-line no-undef
66764
+ }).then(() => {
66765
+ BasisModule.initializeBasis();
66766
+ if (BasisModule.KTX2File === undefined) {
66767
+ console.warn('KTX2TextureTranscoder: Please update Basis Universal transcoder.');
66768
+ }
66769
+ });
66770
+ }
66771
+
66772
+ function transcode(buffer) {
66773
+ const ktx2File = new BasisModule.KTX2File(new Uint8Array(buffer));
66774
+
66775
+ function cleanup() {
66776
+ ktx2File.close();
66777
+ ktx2File.delete();
66778
+ }
66779
+
66780
+ if (!ktx2File.isValid()) {
66781
+ cleanup();
66782
+ throw new Error('KTX2TextureTranscoder: Invalid or unsupported .ktx2 file');
66783
+ }
66784
+ const basisFormat = ktx2File.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S;
66785
+ const width = ktx2File.getWidth();
66786
+ const height = ktx2File.getHeight();
66787
+ const levels = ktx2File.getLevels();
66788
+ const hasAlpha = ktx2File.getHasAlpha();
66789
+ const dfdTransferFn = ktx2File.getDFDTransferFunc();
66790
+ const dfdFlags = ktx2File.getDFDFlags();
66791
+ const {transcoderFormat, engineFormat} = getTranscoderFormat(basisFormat, width, height, hasAlpha);
66792
+ if (!width || !height || !levels) {
66793
+ cleanup();
66794
+ throw new Error('KTX2TextureTranscoder: Invalid texture');
66795
+ }
66796
+ if (!ktx2File.startTranscoding()) {
66797
+ cleanup();
66798
+ throw new Error('KTX2TextureTranscoder: .startTranscoding failed');
66799
+ }
66800
+ const mipmaps = [];
66801
+ for (let mip = 0; mip < levels; mip++) {
66802
+ const levelInfo = ktx2File.getImageLevelInfo(mip, 0, 0);
66803
+ const mipWidth = levelInfo.origWidth;
66804
+ const mipHeight = levelInfo.origHeight;
66805
+ const dst = new Uint8Array(ktx2File.getImageTranscodedSizeInBytes(mip, 0, 0, transcoderFormat));
66806
+ const status = ktx2File.transcodeImage(dst, mip, 0, 0, transcoderFormat, 0, -1, -1);
66807
+ if (!status) {
66808
+ cleanup();
66809
+ throw new Error('KTX2TextureTranscoder: .transcodeImage failed.');
66810
+ }
66811
+ mipmaps.push({data: dst, width: mipWidth, height: mipHeight});
66812
+ }
66813
+ cleanup();
66814
+ return {width, height, hasAlpha, mipmaps, format: engineFormat, dfdTransferFn, dfdFlags};
66815
+ }
66816
+
66817
+ // Optimal choice of a transcoder target format depends on the Basis format (ETC1S or UASTC),
66818
+ // device capabilities, and texture dimensions. The list below ranks the formats separately
66819
+ // for ETC1S and UASTC.
66820
+ //
66821
+ // In some cases, transcoding UASTC to RGBA32 might be preferred for higher quality (at
66822
+ // significant memory cost) compared to ETC1/2, BC1/3, and PVRTC. The transcoder currently
66823
+ // chooses RGBA32 only as a last resort and does not expose that option to the caller.
66824
+
66825
+ const FORMAT_OPTIONS = [{
66826
+ if: 'astcSupported',
66827
+ basisFormat: [BasisFormat.UASTC_4x4],
66828
+ transcoderFormat: [TranscoderFormat.ASTC_4x4, TranscoderFormat.ASTC_4x4],
66829
+ engineFormat: [EngineFormat.RGBA_ASTC_4x4_Format, EngineFormat.RGBA_ASTC_4x4_Format],
66830
+ priorityETC1S: Infinity,
66831
+ priorityUASTC: 1,
66832
+ needsPowerOfTwo: false
66833
+ }, {
66834
+ if: 'bptcSupported',
66835
+ basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
66836
+ transcoderFormat: [TranscoderFormat.BC7_M5, TranscoderFormat.BC7_M5],
66837
+ engineFormat: [EngineFormat.RGBA_BPTC_Format, EngineFormat.RGBA_BPTC_Format],
66838
+ priorityETC1S: 3,
66839
+ priorityUASTC: 2,
66840
+ needsPowerOfTwo: false
66841
+ }, {
66842
+ if: 'dxtSupported',
66843
+ basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
66844
+ transcoderFormat: [TranscoderFormat.BC1, TranscoderFormat.BC3],
66845
+ engineFormat: [EngineFormat.RGB_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format],
66846
+ priorityETC1S: 4,
66847
+ priorityUASTC: 5,
66848
+ needsPowerOfTwo: false
66849
+ }, {
66850
+ if: 'etc2Supported',
66851
+ basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
66852
+ transcoderFormat: [TranscoderFormat.ETC1, TranscoderFormat.ETC2],
66853
+ engineFormat: [EngineFormat.RGB_ETC2_Format, EngineFormat.RGBA_ETC2_EAC_Format],
66854
+ priorityETC1S: 1,
66855
+ priorityUASTC: 3,
66856
+ needsPowerOfTwo: false
66857
+ }, {
66858
+ if: 'etc1Supported',
66859
+ basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
66860
+ transcoderFormat: [TranscoderFormat.ETC1],
66861
+ engineFormat: [EngineFormat.RGB_ETC1_Format],
66862
+ priorityETC1S: 2,
66863
+ priorityUASTC: 4,
66864
+ needsPowerOfTwo: false
66865
+ }, {
66866
+ if: 'pvrtcSupported',
66867
+ basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
66868
+ transcoderFormat: [TranscoderFormat.PVRTC1_4_RGB, TranscoderFormat.PVRTC1_4_RGBA],
66869
+ engineFormat: [EngineFormat.RGB_PVRTC_4BPPV1_Format, EngineFormat.RGBA_PVRTC_4BPPV1_Format],
66870
+ priorityETC1S: 5,
66871
+ priorityUASTC: 6,
66872
+ needsPowerOfTwo: true
66873
+ }];
66874
+ const ETC1S_OPTIONS = FORMAT_OPTIONS.sort(function (a, b) {
66875
+ return a.priorityETC1S - b.priorityETC1S;
66876
+ });
66877
+ const UASTC_OPTIONS = FORMAT_OPTIONS.sort(function (a, b) {
66878
+ return a.priorityUASTC - b.priorityUASTC;
66879
+ });
66880
+
66881
+ function getTranscoderFormat(basisFormat, width, height, hasAlpha) {
66882
+ let transcoderFormat;
66883
+ let engineFormat;
66884
+ const options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS;
66885
+ for (let i = 0; i < options.length; i++) {
66886
+ const opt = options[i];
66887
+ if (!config[opt.if]) continue;
66888
+ if (!opt.basisFormat.includes(basisFormat)) continue;
66889
+ if (hasAlpha && opt.transcoderFormat.length < 2) continue;
66890
+ if (opt.needsPowerOfTwo && !(isPowerOfTwo(width) && isPowerOfTwo(height))) continue;
66891
+ transcoderFormat = opt.transcoderFormat[hasAlpha ? 1 : 0];
66892
+ engineFormat = opt.engineFormat[hasAlpha ? 1 : 0];
66893
+ return {
66894
+ transcoderFormat,
66895
+ engineFormat
66896
+ };
66897
+ }
66898
+ console.warn('KTX2TextureTranscoder: No suitable compressed texture format found. Decoding to RGBA32.');
66899
+ transcoderFormat = TranscoderFormat.RGBA32;
66900
+ engineFormat = EngineFormat.RGBAFormat;
66901
+ return {
66902
+ transcoderFormat,
66903
+ engineFormat
66904
+ };
66905
+ }
66906
+
66907
+ function isPowerOfTwo(value) {
66908
+ if (value <= 2) return true;
66909
+ return (value & value - 1) === 0 && value !== 0;
66910
+ }
66911
+ };
66912
+
66913
+ const cachedTranscoders = {};
66914
+
66915
+ /**
66916
+ * Returns a new {@link KTX2TextureTranscoder}.
66917
+ *
66918
+ * The ````transcoderPath```` config will be set to: "https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/"
66919
+ *
66920
+ * @private
66921
+ */
66922
+ function getKTX2TextureTranscoder(viewer) {
66923
+ const sceneId = viewer.scene.id;
66924
+ let transcoder = cachedTranscoders[sceneId];
66925
+ if (!transcoder) {
66926
+ transcoder = new KTX2TextureTranscoder({viewer});
66927
+ cachedTranscoders[sceneId] = transcoder;
66928
+ viewer.scene.on("destroyed", () => {
66929
+ delete cachedTranscoders[sceneId];
66930
+ transcoder.destroy();
66931
+ });
66932
+ }
66933
+ return transcoder;
66934
+ }
66935
+
65885
66936
  const tempVec3a$9 = math.vec3();
65886
66937
  const tempMat4$1 = math.mat4();
65887
66938
 
@@ -66957,7 +68008,7 @@ class VBOSceneModel extends Component {
66957
68008
 
66958
68009
  super(owner, cfg);
66959
68010
 
66960
- this._textureTranscoder = cfg.textureTranscoder;
68011
+ this._textureTranscoder = cfg.textureTranscoder || getKTX2TextureTranscoder(this.scene.viewer);
66961
68012
 
66962
68013
  this._maxGeometryBatchSize = cfg.maxGeometryBatchSize;
66963
68014
 
@@ -67933,7 +68984,7 @@ class VBOSceneModel extends Component {
67933
68984
  * @param {String} [cfg.src] Image file for the texture. Assumed to be transcoded if not having a recognized image file
67934
68985
  * extension (jpg, jpeg, png etc.). If transcoded, then assumes ````VBOSceneModel```` is configured with a {@link TextureTranscoder}.
67935
68986
  * @param {ArrayBuffer[]} [cfg.buffers] Transcoded texture data. Assumes ````VBOSceneModel```` is
67936
- * configured with a {@link TextureTranscoder}. Given as an array of buffers so we can potentially support multi-image textures, such as cube maps.
68987
+ * configured with a {@link TextureTranscoder}. This parameter is given as an array of buffers so we can potentially support multi-image textures, such as cube maps.
67937
68988
  * @param {HTMLImageElement} [cfg.image] HTML Image object to load into this texture. Overrides ````src```` and ````buffers````. Never transcoded.
67938
68989
  * @param {Number} [cfg.minFilter=LinearMipmapLinearFilter] How the texture is sampled when a texel covers less than one pixel.
67939
68990
  * Supported values are {@link LinearMipmapLinearFilter}, {@link LinearMipMapNearestFilter}, {@link NearestMipMapNearestFilter}, {@link NearestMipMapLinearFilter} and {@link LinearMipMapLinearFilter}.
@@ -67953,8 +69004,8 @@ class VBOSceneModel extends Component {
67953
69004
  this.error("Texture already created: " + textureId);
67954
69005
  return;
67955
69006
  }
67956
- if (!cfg.src && !cfg.image) {
67957
- this.error("Param expected: `src` or `image'");
69007
+ if (!cfg.src && !cfg.image && !cfg.buffers) {
69008
+ this.error("Param expected: `src`, `image' or 'buffers'");
67958
69009
  return null;
67959
69010
  }
67960
69011
  let minFilter = cfg.minFilter || LinearMipmapLinearFilter;
@@ -74055,7 +75106,7 @@ class WorkerThread {
74055
75106
 
74056
75107
  }
74057
75108
 
74058
- class WorkerPool$1 {
75109
+ class WorkerPool {
74059
75110
  constructor(props) {
74060
75111
  _defineProperty(this, "name", 'unnamed');
74061
75112
 
@@ -74263,7 +75314,7 @@ class WorkerFarm {
74263
75314
  let workerPool = this.workerPools.get(name);
74264
75315
 
74265
75316
  if (!workerPool) {
74266
- workerPool = new WorkerPool$1({
75317
+ workerPool = new WorkerPool({
74267
75318
  name,
74268
75319
  source,
74269
75320
  url
@@ -100442,7 +101493,7 @@ function inflate(deflatedData) {
100442
101493
 
100443
101494
  return {
100444
101495
  metadata: JSON.parse(pako.inflate(deflatedData.metadata, {to: 'string'})),
100445
- textureData: new Uint8ClampedArray(inflate(deflatedData.textureData)),
101496
+ textureData: new Uint8Array(inflate(deflatedData.textureData)),
100446
101497
  eachTextureDataPortion: new Uint32Array(inflate(deflatedData.eachTextureDataPortion)),
100447
101498
  eachTextureDimensions: new Uint16Array(inflate(deflatedData.eachTextureDimensions)),
100448
101499
  positions: new Uint16Array(inflate(deflatedData.positions)),
@@ -100482,7 +101533,7 @@ const decompressColor = (function () {
100482
101533
  };
100483
101534
  })();
100484
101535
 
100485
- const imagDataToImage = (function () {
101536
+ ((function () {
100486
101537
  const canvas = document.createElement('canvas');
100487
101538
  const context = canvas.getContext('2d');
100488
101539
  return function (imagedata) {
@@ -100491,14 +101542,14 @@ const imagDataToImage = (function () {
100491
101542
  context.putImageData(imagedata, 0, 0);
100492
101543
  return canvas.toDataURL();
100493
101544
  };
100494
- })();
101545
+ }))();
100495
101546
 
100496
101547
  function load(viewer, options, inflatedData, sceneModel) {
100497
101548
 
100498
101549
  const metadata = inflatedData.metadata;
100499
101550
  const textureData = inflatedData.textureData;
100500
101551
  const eachTextureDataPortion = inflatedData.eachTextureDataPortion;
100501
- const eachTextureDimensions = inflatedData.eachTextureDimensions;
101552
+ inflatedData.eachTextureDimensions;
100502
101553
  const positions = inflatedData.positions;
100503
101554
  const normals = inflatedData.normals;
100504
101555
  const colors = inflatedData.colors;
@@ -100559,20 +101610,13 @@ function load(viewer, options, inflatedData, sceneModel) {
100559
101610
  const textureDataPortionSize = textureDataPortionEnd - textureDataPortionStart;
100560
101611
  const textureDataPortionExists = (textureDataPortionSize > 0);
100561
101612
  if (textureDataPortionExists) {
100562
- const imageDataSubarray = textureData.subarray(textureDataPortionStart, textureDataPortionEnd);
100563
- const width = eachTextureDimensions[textureIndex * 2 + 0];
100564
- const height = eachTextureDimensions[textureIndex * 2 + 1];
100565
- const imageData = new ImageData(imageDataSubarray, width, height);
100566
-
100567
- //////////////////////////////////////////////////////////////
100568
- // TODO: This is super inefficient - replace with Basis:
100569
- //////////////////////////////////////////////////////////////
100570
101613
 
100571
- const image = imagDataToImage(imageData);
101614
+ const imageDataSubarray = new Uint8Array(textureData.subarray(textureDataPortionStart, textureDataPortionEnd));
101615
+ const arrayBuffer = imageDataSubarray.buffer;
100572
101616
 
100573
101617
  sceneModel.createTexture({
100574
101618
  id: `texture-${textureIndex}`,
100575
- src: image
101619
+ buffers: [arrayBuffer]
100576
101620
  });
100577
101621
  }
100578
101622
  }
@@ -100994,6 +102038,7 @@ parsers[ParserV10.version] = ParserV10;
100994
102038
  * * An *````.XKT````* file is a single BLOB containing a model, compressed using geometry quantization
100995
102039
  * and [pako](https://nodeca.github.io/pako/).
100996
102040
  * * Supports double-precision coordinates.
102041
+ * * Supports compressed textures.
100997
102042
  * * Set the position, scale and rotation of each model as you load it.
100998
102043
  * * Filter which IFC types get loaded.
100999
102044
  * * Configure initial default appearances for IFC types.
@@ -101112,17 +102157,26 @@ parsers[ParserV10.version] = ParserV10;
101112
102157
  * model.destroy();
101113
102158
  * ````
101114
102159
  *
101115
- * ## Loading XKT files containing KTX2 textures
102160
+ * ## Loading XKT files containing textures
101116
102161
  *
101117
- * An XKTLoaderPlugin that is configured with a {@link KTX2TextureTranscoder} will allow us to load XKT files that
101118
- * contain KTX2 textures. If we don't configure a KTX2TextureTranscoder, then the XKTLoaderPlugin will simply ignore
101119
- * the textures in the XKT.
102162
+ * XKTLoaderPlugin uses a {@link KTX2TextureTranscoder} to load textures in XKT files (XKT v10+). An XKTLoaderPlugin has its own
102163
+ * default KTX2TextureTranscoder, configured to load the Basis Codec from the CDN. If we wish, we can override that with our own
102164
+ * KTX2TextureTranscoder instance that's configured to load the Codec locally.
101120
102165
  *
101121
102166
  * In the example below, we'll create a {@link Viewer} and add an XKTLoaderPlugin
101122
- * configured with a KTX2TextureTranscoder. Then we'll use the XKTLoaderPlugin to load an
101123
- * XKT file that contains KTX2 textures, which the plugin will transcode using
102167
+ * configured with a KTX2TextureTranscoder that finds the Codec in our local file system. Then we'll use the
102168
+ * XKTLoaderPlugin to load an XKT file that contains KTX2 textures, which the plugin will transcode using
101124
102169
  * its KTX2TextureTranscoder.
101125
102170
  *
102171
+ * We'll configure our KTX2TextureTranscoder to load the Basis Codec from a local directory. If we were happy with loading the
102172
+ * Codec from our CDN (ie. our app will always have an Internet connection) then we could just leave out the
102173
+ * KTX2TextureTranscoder altogether, and let the XKTLoaderPlugin use its internal default KTX2TextureTranscoder, which is configured to
102174
+ * load the Codec from the CDN. We'll stick with loading our own Codec, in case we want to run our app without an Internet connection.
102175
+ *
102176
+ * <a href="https://xeokit.github.io/xeokit-sdk/examples/#loading_XKT_Textures_HousePlan"><img src="https://xeokit.github.io/xeokit-sdk/assets/images/xktWithTextures.png"></a>
102177
+ *
102178
+ * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XKT_Textures_HousePlan)]
102179
+ *
101126
102180
  * ````javascript
101127
102181
  * const viewer = new Viewer({
101128
102182
  * canvasId: "myCanvas",
@@ -154208,1016 +155262,6 @@ class PerformanceModel extends VBOSceneModel {
154208
155262
  }
154209
155263
  }
154210
155264
 
154211
- class LoadingManager {
154212
-
154213
- constructor(onLoad, onProgress, onError) {
154214
-
154215
- this.isLoading = false;
154216
- this.itemsLoaded = 0;
154217
- this.itemsTotal = 0;
154218
- this.urlModifier = undefined;
154219
- this.handlers = [];
154220
-
154221
- this.onStart = undefined;
154222
- this.onLoad = onLoad;
154223
- this.onProgress = onProgress;
154224
- this.onError = onError;
154225
- }
154226
-
154227
- itemStart(url) {
154228
- this.itemsTotal++;
154229
- if (this.isLoading === false) {
154230
- if (this.onStart !== undefined) {
154231
- this.onStart(url, this.itemsLoaded, this.itemsTotal);
154232
- }
154233
- }
154234
- this.isLoading = true;
154235
- }
154236
-
154237
- itemEnd(url) {
154238
- this.itemsLoaded++;
154239
- if (this.onProgress !== undefined) {
154240
- this.onProgress(url, this.itemsLoaded, this.itemsTotal);
154241
- }
154242
- if (this.itemsLoaded === this.itemsTotal) {
154243
- this.isLoading = false;
154244
- if (this.onLoad !== undefined) {
154245
- this.onLoad();
154246
- }
154247
- }
154248
- }
154249
-
154250
- itemError(url) {
154251
- if (this.onError !== undefined) {
154252
- this.onError(url);
154253
- }
154254
- }
154255
-
154256
- resolveURL(url) {
154257
- if (this.urlModifier) {
154258
- return this.urlModifier(url);
154259
- }
154260
- return url;
154261
- }
154262
-
154263
- setURLModifier(transform) {
154264
- this.urlModifier = transform;
154265
- return this;
154266
- }
154267
-
154268
- addHandler(regex, loader) {
154269
- this.handlers.push(regex, loader);
154270
- return this;
154271
- }
154272
-
154273
- removeHandler(regex) {
154274
- const index = this.handlers.indexOf(regex);
154275
- if (index !== -1) {
154276
- this.handlers.splice(index, 2);
154277
- }
154278
- return this;
154279
- }
154280
-
154281
- getHandler(file) {
154282
- for (let i = 0, l = this.handlers.length; i < l; i += 2) {
154283
- const regex = this.handlers[i];
154284
- const loader = this.handlers[i + 1];
154285
- if (regex.global) regex.lastIndex = 0; // see #17920
154286
- if (regex.test(file)) {
154287
- return loader;
154288
- }
154289
- }
154290
- return null;
154291
- }
154292
- }
154293
-
154294
- const DefaultLoadingManager = new LoadingManager();
154295
-
154296
- class Loader {
154297
-
154298
- constructor(manager) {
154299
-
154300
- this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
154301
-
154302
- this.crossOrigin = 'anonymous';
154303
- this.withCredentials = false;
154304
- this.path = '';
154305
- this.resourcePath = '';
154306
- this.requestHeader = {};
154307
- }
154308
-
154309
- load( /* url, onLoad, onProgress, onError */) {
154310
- }
154311
-
154312
- loadAsync(url, onProgress) {
154313
- const scope = this;
154314
- return new Promise(function (resolve, reject) {
154315
- scope.load(url, resolve, onProgress, reject);
154316
- });
154317
- }
154318
-
154319
- parse( /* data */) {
154320
- }
154321
-
154322
- setCrossOrigin(crossOrigin) {
154323
- this.crossOrigin = crossOrigin;
154324
- return this;
154325
- }
154326
-
154327
- setWithCredentials(value) {
154328
- this.withCredentials = value;
154329
- return this;
154330
- }
154331
-
154332
- setPath(path) {
154333
- this.path = path;
154334
- return this;
154335
- }
154336
-
154337
- setResourcePath(resourcePath) {
154338
- this.resourcePath = resourcePath;
154339
- return this;
154340
- }
154341
-
154342
- setRequestHeader(requestHeader) {
154343
- this.requestHeader = requestHeader;
154344
- return this;
154345
- }
154346
- }
154347
-
154348
- /**
154349
- * @author Deepkolos / https://github.com/deepkolos
154350
- */
154351
-
154352
- class WorkerPool {
154353
-
154354
- constructor(pool = 4) {
154355
- this.pool = pool;
154356
- this.queue = [];
154357
- this.workers = [];
154358
- this.workersResolve = [];
154359
- this.workerStatus = 0;
154360
- }
154361
-
154362
- _initWorker(workerId) {
154363
- if (!this.workers[workerId]) {
154364
- const worker = this.workerCreator();
154365
- worker.addEventListener('message', this._onMessage.bind(this, workerId));
154366
- this.workers[workerId] = worker;
154367
- }
154368
- }
154369
-
154370
- _getIdleWorker() {
154371
- for (let i = 0; i < this.pool; i++)
154372
- if (!(this.workerStatus & (1 << i))) return i;
154373
- return -1;
154374
- }
154375
-
154376
- _onMessage(workerId, msg) {
154377
- const resolve = this.workersResolve[workerId];
154378
- resolve && resolve(msg);
154379
- if (this.queue.length) {
154380
- const {resolve, msg, transfer} = this.queue.shift();
154381
- this.workersResolve[workerId] = resolve;
154382
- this.workers[workerId].postMessage(msg, transfer);
154383
- } else {
154384
- this.workerStatus ^= 1 << workerId;
154385
- }
154386
- }
154387
-
154388
- setWorkerCreator(workerCreator) {
154389
- this.workerCreator = workerCreator;
154390
- }
154391
-
154392
- setWorkerLimit(pool) {
154393
- this.pool = pool;
154394
- }
154395
-
154396
- postMessage(msg, transfer) {
154397
- return new Promise((resolve) => {
154398
- const workerId = this._getIdleWorker();
154399
- if (workerId !== -1) {
154400
- this._initWorker(workerId);
154401
- this.workerStatus |= 1 << workerId;
154402
- this.workersResolve[workerId] = resolve;
154403
- this.workers[workerId].postMessage(msg, transfer);
154404
- } else {
154405
- this.queue.push({resolve, msg, transfer});
154406
- }
154407
- });
154408
- }
154409
-
154410
- destroy() {
154411
-
154412
- this.workers.forEach((worker) => worker.terminate());
154413
- this.workersResolve.length = 0;
154414
- this.workers.length = 0;
154415
- this.queue.length = 0;
154416
- this.workerStatus = 0;
154417
-
154418
- }
154419
-
154420
- }
154421
-
154422
- /**
154423
- * Transcodes texture data.
154424
- *
154425
- * A {@link SceneModel} configured with an appropriate TextureTranscoder will allow us to add textures from
154426
- * transcoded buffers or files. For a concrete example, see {@link VBOSceneModel}, which can be configured with
154427
- * a {@link KTX2TextureTranscoder}, which allows us to add textures from KTX2 buffers and files.
154428
- *
154429
- * @interface
154430
- */
154431
- class TextureTranscoder {
154432
-
154433
- /**
154434
- * Transcodes texture data from transcoded buffers into a {@link Texture2D}.
154435
- *
154436
- * @param {ArrayBuffer[]} buffers Transcoded texture data. Given as an array of buffers so that we can support
154437
- * multi-image textures, such as cube maps.
154438
- * @param {*} config Transcoding options.
154439
- * @param {Texture2D} texture The texture to load.
154440
- * @returns {Promise} Resolves when the texture has loaded.
154441
- */
154442
- transcode(buffers, texture, config = {}) {
154443
- }
154444
-
154445
- /**
154446
- * Destroys this transcoder.
154447
- */
154448
- destroy() {
154449
- }
154450
- }
154451
-
154452
- const Cache = {
154453
-
154454
- enabled: false,
154455
- files: {},
154456
-
154457
- add: function (key, file) {
154458
- if (this.enabled === false) {
154459
- return;
154460
- }
154461
- this.files[key] = file;
154462
- },
154463
-
154464
- get: function (key) {
154465
- if (this.enabled === false) {
154466
- return;
154467
- }
154468
- return this.files[key];
154469
- },
154470
-
154471
- remove: function (key) {
154472
- delete this.files[key];
154473
- },
154474
-
154475
- clear: function () {
154476
- this.files = {};
154477
- }
154478
- };
154479
-
154480
- const loading = {};
154481
-
154482
- class FileLoader extends Loader {
154483
-
154484
- constructor(manager) {
154485
- super(manager);
154486
- }
154487
-
154488
- load(url, onLoad, onProgress, onError) {
154489
- if (url === undefined) {
154490
- url = '';
154491
- }
154492
- if (this.path !== undefined) {
154493
- url = this.path + url;
154494
- }
154495
- url = this.manager.resolveURL(url);
154496
- const cached = Cache.get(url);
154497
- if (cached !== undefined) {
154498
- this.manager.itemStart(url);
154499
- setTimeout(() => {
154500
- if (onLoad) {
154501
- onLoad(cached);
154502
- }
154503
- this.manager.itemEnd(url);
154504
- }, 0);
154505
- return cached;
154506
- }
154507
- if (loading[url] !== undefined) {
154508
- loading[url].push({onLoad, onProgress, onError});
154509
- return;
154510
- }
154511
- loading[url] = [];
154512
- loading[url].push({onLoad, onProgress, onError});
154513
- const req = new Request(url, {
154514
- headers: new Headers(this.requestHeader),
154515
- credentials: this.withCredentials ? 'include' : 'same-origin'
154516
- });
154517
- const mimeType = this.mimeType;
154518
- const responseType = this.responseType;
154519
- fetch(req).then(response => {
154520
- if (response.status === 200 || response.status === 0) {
154521
- // Some browsers return HTTP Status 0 when using non-http protocol
154522
- // e.g. 'file://' or 'data://'. Handle as success.
154523
- if (response.status === 0) {
154524
- console.warn('FileLoader: HTTP Status 0 received.');
154525
- }
154526
- if (typeof ReadableStream === 'undefined' || response.body.getReader === undefined) {
154527
- return response;
154528
- }
154529
- const callbacks = loading[url];
154530
- const reader = response.body.getReader();
154531
- const contentLength = response.headers.get('Content-Length');
154532
- const total = contentLength ? parseInt(contentLength) : 0;
154533
- const lengthComputable = total !== 0;
154534
- let loaded = 0;
154535
- const stream = new ReadableStream({
154536
- start(controller) {
154537
- readData();
154538
-
154539
- function readData() {
154540
- reader.read().then(({done, value}) => {
154541
- if (done) {
154542
- controller.close();
154543
- } else {
154544
- loaded += value.byteLength;
154545
- const event = new ProgressEvent('progress', {lengthComputable, loaded, total});
154546
- for (let i = 0, il = callbacks.length; i < il; i++) {
154547
- const callback = callbacks[i];
154548
- if (callback.onProgress) {
154549
- callback.onProgress(event);
154550
- }
154551
- }
154552
- controller.enqueue(value);
154553
- readData();
154554
- }
154555
- });
154556
- }
154557
- }
154558
- });
154559
- return new Response(stream);
154560
- } else {
154561
- throw Error(`fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`);
154562
- }
154563
- }).then(response => {
154564
- switch (responseType) {
154565
- case 'arraybuffer':
154566
- return response.arrayBuffer();
154567
- case 'blob':
154568
- return response.blob();
154569
- case 'document':
154570
- return response.text()
154571
- .then(text => {
154572
- const parser = new DOMParser();
154573
- return parser.parseFromString(text, mimeType);
154574
- });
154575
- case 'json':
154576
- return response.json();
154577
- default:
154578
- if (mimeType === undefined) {
154579
- return response.text();
154580
- } else {
154581
- // sniff encoding
154582
- const re = /charset="?([^;"\s]*)"?/i;
154583
- const exec = re.exec(mimeType);
154584
- const label = exec && exec[1] ? exec[1].toLowerCase() : undefined;
154585
- const decoder = new TextDecoder(label);
154586
- return response.arrayBuffer().then(ab => decoder.decode(ab));
154587
- }
154588
- }
154589
- }).then(data => {
154590
- // Add to cache only on HTTP success, so that we do not cache
154591
- // error response bodies as proper responses to requests.
154592
- Cache.add(url, data);
154593
- const callbacks = loading[url];
154594
- delete loading[url];
154595
- for (let i = 0, il = callbacks.length; i < il; i++) {
154596
- const callback = callbacks[i];
154597
- if (callback.onLoad) {
154598
- callback.onLoad(data);
154599
- }
154600
- }
154601
- }).catch(err => {
154602
- // Abort errors and other errors are handled the same
154603
- const callbacks = loading[url];
154604
- if (callbacks === undefined) {
154605
- // When onLoad was called and url was deleted in `loading`
154606
- this.manager.itemError(url);
154607
- throw err;
154608
-
154609
- }
154610
- delete loading[url];
154611
- for (let i = 0, il = callbacks.length; i < il; i++) {
154612
- const callback = callbacks[i];
154613
- if (callback.onError) {
154614
- callback.onError(err);
154615
- }
154616
- }
154617
- this.manager.itemError(url);
154618
- }).finally(() => {
154619
- this.manager.itemEnd(url);
154620
- });
154621
- this.manager.itemStart(url);
154622
- }
154623
-
154624
- setResponseType(value) {
154625
- this.responseType = value;
154626
- return this;
154627
- }
154628
-
154629
- setMimeType(value) {
154630
- this.mimeType = value;
154631
- return this;
154632
- }
154633
- }
154634
-
154635
- const KTX2TransferSRGB = 2;
154636
- const KTX2_ALPHA_PREMULTIPLIED = 1;
154637
-
154638
- let activeTranscoders = 0;
154639
-
154640
- /**
154641
- * Transcodes texture data from KTX2.
154642
- *
154643
- * ## Overview
154644
- *
154645
- * * Uses the Basis Universal codec to transcode KTX2 texture assets.
154646
- * * An {@link XKTLoaderPlugin} that is configured with a KTX2TextureTranscoder will allow us to load KTX2 textures in
154647
- * XKT files. Textures in XKT are always KTX2. If we do not configure a KTX2TextureTranscoder, the XKTLoaderPlugin will
154648
- * simply ignore the textures in the XKT.
154649
- * * A {@link SceneModel} implementation (eg. {@link VBOSceneModel}) that is configured with a KTX2TextureTranscoder will
154650
- * allow us to load textures into it from KTX2 files or ArrayBuffers.
154651
- *
154652
- * ## What is KTX2?
154653
- *
154654
- * A KTX2 file stores GPU texture data in the Khronos Texture 2.0 (KTX2) container format. It contains image data for
154655
- * a texture asset compressed with Basis Universal (BasisU) supercompression that can be transcoded to different formats
154656
- * depending on the support provided by the target devices. KTX2 provides a lightweight format for distributing texture
154657
- * assets to GPUs. Due to BasisU compression, KTX2 files can store any image format supported by GPUs.
154658
- *
154659
- * ## Loading XKT files containing KTX2 textures
154660
- *
154661
- * An {@link XKTLoaderPlugin} that is configured with a KTX2TextureTranscoder will allow us to load XKT files that
154662
- * contain KTX2 textures. If we don't configure a KTX2TextureTranscoder, then the XKTLoaderPlugin will simply ignore
154663
- * the textures in the XKT.
154664
- *
154665
- * In the example below, we'll create a {@link Viewer} and add an {@link XKTLoaderPlugin}
154666
- * configured with a KTX2TextureTranscoder. Then we'll use the XKTLoaderPlugin to load an
154667
- * XKT file that contains KTX2 textures, which the plugin will transcode using
154668
- * its KTX2TextureTranscoder.
154669
- *
154670
- * ````javascript
154671
- * const viewer = new Viewer({
154672
- * canvasId: "myCanvas",
154673
- * transparent: true
154674
- * });
154675
- *
154676
- * viewer.camera.eye = [-2.56, 8.38, 8.27];
154677
- * viewer.camera.look = [13.44, 3.31, -14.83];
154678
- * viewer.camera.up = [0.10, 0.98, -0.14];
154679
- *
154680
- * const textureTranscoder = new KTX2TextureTranscoder({
154681
- * viewer,
154682
- * transcoderPath: "./../dist/basis/" // <------ Path to Basis Universal transcoder
154683
- * });
154684
- *
154685
- * const xktLoader = new XKTLoaderPlugin(viewer, {
154686
- * textureTranscoder // <<------------- Transcodes KTX2 textures in XKT files
154687
- * });
154688
- *
154689
- * const sceneModel = xktLoader.load({
154690
- * id: "myModel",
154691
- * src: "./HousePlan.xkt" // <<------ XKT file with KTX2 textures
154692
- * });
154693
- * ````
154694
- *
154695
- * ## Loading KTX2 files into a VBOSceneModel
154696
- *
154697
- * A {@link SceneModel} that is configured with a KTX2TextureTranscoder will
154698
- * allow us to load textures into it from KTX2-transcoded buffers or files.
154699
- *
154700
- * In the example below, we'll create a {@link Viewer}, containing a {@link VBOSceneModel} configured with a
154701
- * KTX2TextureTranscoder. We'll then programmatically create a simple object within the VBOSceneModel, consisting of
154702
- * a single mesh with a texture loaded from a KTX2 file, which our VBOSceneModel internally transcodes, using
154703
- * its KTX2TextureTranscoder. Note how we configure our KTX2TextureTranscoder with a path to the Basis Universal
154704
- * transcoder WASM module.
154705
- *
154706
- * ````javascript
154707
- * const viewer = new Viewer({
154708
- * canvasId: "myCanvas",
154709
- * transparent: true
154710
- * });
154711
- *
154712
- * viewer.scene.camera.eye = [-21.80, 4.01, 6.56];
154713
- * viewer.scene.camera.look = [0, -5.75, 0];
154714
- * viewer.scene.camera.up = [0.37, 0.91, -0.11];
154715
- *
154716
- * const textureTranscoder = new KTX2TextureTranscoder({
154717
- * viewer,
154718
- * transcoderPath: "./../dist/basis/" // <------ Path to BasisU transcoder module
154719
- * });
154720
- *
154721
- * const vboSceneModel = new VBOSceneModel(viewer.scene, {
154722
- * id: "myModel",
154723
- * textureTranscoder // <<-------------------- Configure model with our transcoder
154724
- * });
154725
- *
154726
- * vboSceneModel.createTexture({
154727
- * id: "myColorTexture",
154728
- * src: "../assets/textures/compressed/sample_uastc_zstd.ktx2" // <<----- KTX2 texture asset
154729
- * });
154730
- *
154731
- * vboSceneModel.createTexture({
154732
- * id: "myMetallicRoughnessTexture",
154733
- * src: "../assets/textures/alpha/crosshatchAlphaMap.jpg" // <<----- JPEG texture asset
154734
- * });
154735
- *
154736
- * vboSceneModel.createTextureSet({
154737
- * id: "myTextureSet",
154738
- * colorTextureId: "myColorTexture",
154739
- * metallicRoughnessTextureId: "myMetallicRoughnessTexture"
154740
- * });
154741
- *
154742
- * vboSceneModel.createMesh({
154743
- * id: "myMesh",
154744
- * textureSetId: "myTextureSet",
154745
- * primitive: "triangles",
154746
- * positions: [1, 1, 1, ...],
154747
- * normals: [0, 0, 1, 0, ...],
154748
- * uv: [1, 0, 0, ...],
154749
- * indices: [0, 1, 2, ...],
154750
- * });
154751
- *
154752
- * vboSceneModel.createEntity({
154753
- * id: "myEntity",
154754
- * meshIds: ["myMesh"]
154755
- * });
154756
- *
154757
- * vboSceneModel.finalize();
154758
- * ````
154759
- *
154760
- * ## Loading KTX2 ArrayBuffers into a VBOSceneModel
154761
- *
154762
- * A {@link SceneModel} that is configured with a KTX2TextureTranscoder will allow us to load textures into
154763
- * it from KTX2 ArrayBuffers.
154764
- *
154765
- * In the example below, we'll create a {@link Viewer}, containing a {@link VBOSceneModel} configured with a
154766
- * KTX2TextureTranscoder. We'll then programmatically create a simple object within the VBOSceneModel, consisting of
154767
- * a single mesh with a texture loaded from a KTX2 ArrayBuffer, which our VBOSceneModel internally transcodes, using
154768
- * its KTX2TextureTranscoder.
154769
- *
154770
- * ````javascript
154771
- * const viewer = new Viewer({
154772
- * canvasId: "myCanvas",
154773
- * transparent: true
154774
- * });
154775
- *
154776
- * viewer.scene.camera.eye = [-21.80, 4.01, 6.56];
154777
- * viewer.scene.camera.look = [0, -5.75, 0];
154778
- * viewer.scene.camera.up = [0.37, 0.91, -0.11];
154779
- *
154780
- * const textureTranscoder = new KTX2TextureTranscoder({
154781
- * viewer,
154782
- * transcoderPath: "./../dist/basis/" // <------ Path to BasisU transcoder module
154783
- * });
154784
- *
154785
- * const vboSceneModel = new VBOSceneModel(viewer.scene, {
154786
- * id: "myModel",
154787
- * textureTranscoder // <<-------------------- Configure model with our transcoder
154788
- * });
154789
- *
154790
- * utils.loadArraybuffer("../assets/textures/compressed/sample_uastc_zstd.ktx2",(arrayBuffer) => {
154791
- *
154792
- * vboSceneModel.createTexture({
154793
- * id: "myColorTexture",
154794
- * buffers: [arrayBuffer] // <<----- KTX2 texture asset
154795
- * });
154796
- *
154797
- * vboSceneModel.createTexture({
154798
- * id: "myMetallicRoughnessTexture",
154799
- * src: "../assets/textures/alpha/crosshatchAlphaMap.jpg" // <<----- JPEG texture asset
154800
- * });
154801
- *
154802
- * vboSceneModel.createTextureSet({
154803
- * id: "myTextureSet",
154804
- * colorTextureId: "myColorTexture",
154805
- * metallicRoughnessTextureId: "myMetallicRoughnessTexture"
154806
- * });
154807
- *
154808
- * vboSceneModel.createMesh({
154809
- * id: "myMesh",
154810
- * textureSetId: "myTextureSet",
154811
- * primitive: "triangles",
154812
- * positions: [1, 1, 1, ...],
154813
- * normals: [0, 0, 1, 0, ...],
154814
- * uv: [1, 0, 0, ...],
154815
- * indices: [0, 1, 2, ...],
154816
- * });
154817
- *
154818
- * vboSceneModel.createEntity({
154819
- * id: "myEntity",
154820
- * meshIds: ["myMesh"]
154821
- * });
154822
- *
154823
- * vboSceneModel.finalize();
154824
- * });
154825
- * ````
154826
- *
154827
- * @implements {TextureTranscoder}
154828
- */
154829
- class KTX2TextureTranscoder {
154830
-
154831
- /**
154832
- * Creates a new KTX2TextureTranscoder.
154833
- *
154834
- * @param {Viewer} viewer The Viewer that our KTX2TextureTranscoder will be used with. This KTX2TextureTranscoder
154835
- * must only be used to transcode textures for this Viewer. This is because the Viewer's capabilities will decide
154836
- * what target GPU formats this KTX2TextureTranscoder will transcode to.
154837
- * @param {String} transcoderPath Path to the Basis transcoder module that internally does the heavy lifting for our KTX2TextureTranscoder.
154838
- * @param {Number} [workerLimit] The maximum number of Workers to use for transcoding.
154839
- */
154840
- constructor({viewer, transcoderPath, workerLimit}) {
154841
-
154842
- this._transcoderPath = transcoderPath;
154843
- this._transcoderBinary = null;
154844
- this._transcoderPending = null;
154845
- this._workerPool = new WorkerPool();
154846
- this._workerSourceURL = '';
154847
-
154848
- if (workerLimit) {
154849
- this._workerPool.setWorkerLimit(workerLimit);
154850
- }
154851
-
154852
- const viewerCapabilities = viewer.capabilities;
154853
-
154854
- this._workerConfig = {
154855
- astcSupported: viewerCapabilities.astcSupported,
154856
- etc1Supported: viewerCapabilities.etc1Supported,
154857
- etc2Supported: viewerCapabilities.etc2Supported,
154858
- dxtSupported: viewerCapabilities.dxtSupported,
154859
- bptcSupported: viewerCapabilities.bptcSupported,
154860
- pvrtcSupported: viewerCapabilities.pvrtcSupported
154861
- };
154862
-
154863
- this._supportedFileTypes = ["xkt2"];
154864
- }
154865
-
154866
- _init() {
154867
- if (!this._transcoderPending) {
154868
- const jsLoader = new FileLoader();
154869
- jsLoader.setPath(this._transcoderPath);
154870
- jsLoader.setWithCredentials(this.withCredentials);
154871
- const jsContent = jsLoader.loadAsync('basis_transcoder.js');
154872
- const binaryLoader = new FileLoader();
154873
- binaryLoader.setPath(this._transcoderPath);
154874
- binaryLoader.setResponseType('arraybuffer');
154875
- binaryLoader.setWithCredentials(this.withCredentials);
154876
- const binaryContent = binaryLoader.loadAsync('basis_transcoder.wasm');
154877
- this._transcoderPending = Promise.all([jsContent, binaryContent])
154878
- .then(([jsContent, binaryContent]) => {
154879
- const fn = KTX2TextureTranscoder.BasisWorker.toString();
154880
- const body = [
154881
- '/* constants */',
154882
- 'let _EngineFormat = ' + JSON.stringify(KTX2TextureTranscoder.EngineFormat),
154883
- 'let _TranscoderFormat = ' + JSON.stringify(KTX2TextureTranscoder.TranscoderFormat),
154884
- 'let _BasisFormat = ' + JSON.stringify(KTX2TextureTranscoder.BasisFormat),
154885
- '/* basis_transcoder.js */',
154886
- jsContent,
154887
- '/* worker */',
154888
- fn.substring(fn.indexOf('{') + 1, fn.lastIndexOf('}'))
154889
- ].join('\n');
154890
- this._workerSourceURL = URL.createObjectURL(new Blob([body]));
154891
- this._transcoderBinary = binaryContent;
154892
- this._workerPool.setWorkerCreator(() => {
154893
- const worker = new Worker(this._workerSourceURL);
154894
- const transcoderBinary = this._transcoderBinary.slice(0);
154895
- worker.postMessage({
154896
- type: 'init',
154897
- config: this._workerConfig,
154898
- transcoderBinary
154899
- }, [transcoderBinary]);
154900
- return worker;
154901
- });
154902
- });
154903
- if (activeTranscoders > 0) {
154904
- console.warn('KTX2TextureTranscoder: Multiple active KTX2TextureTranscoder may cause performance issues.' + ' Use a single KTX2TextureTranscoder instance, or call .dispose() on old instances.');
154905
- }
154906
- activeTranscoders++;
154907
- }
154908
- return this._transcoderPending;
154909
- }
154910
-
154911
- /**
154912
- * Transcodes texture data from transcoded buffers into a {@link Texture2D}.
154913
- *
154914
- * @param {ArrayBuffer[]} buffers Transcoded texture data. Given as an array of buffers so that we can support multi-image textures, such as cube maps.
154915
- * @param {*} config Transcoding options.
154916
- * @param {Texture2D} texture The texture to load.
154917
- * @returns {Promise} Resolves when the texture has loaded.
154918
- */
154919
- transcode(buffers, texture, config = {}) {
154920
- return new Promise((resolve, reject) => {
154921
- const taskConfig = config;
154922
- this._init().then(() => {
154923
- return this._workerPool.postMessage({
154924
- type: 'transcode',
154925
- buffers,
154926
- taskConfig: taskConfig
154927
- }, buffers);
154928
- }).then((e) => {
154929
- const transcodeResult = e.data;
154930
- const {mipmaps, width, height, format, type, error, dfdTransferFn, dfdFlags} = transcodeResult;
154931
- if (type === 'error') {
154932
- return reject(error);
154933
- }
154934
- texture.setCompressedData({
154935
- mipmaps,
154936
- props: {
154937
- format: format,
154938
- minFilter: mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter,
154939
- magFilter: mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter,
154940
- encoding: dfdTransferFn === KTX2TransferSRGB ? sRGBEncoding : LinearEncoding,
154941
- premultiplyAlpha : !!(dfdFlags & KTX2_ALPHA_PREMULTIPLIED)
154942
- }
154943
- });
154944
- resolve();
154945
- });
154946
- });
154947
- }
154948
-
154949
- /**
154950
- * Destroys this KTX2TextureTranscoder
154951
- */
154952
- destroy() {
154953
- URL.revokeObjectURL(this._workerSourceURL);
154954
- this._workerPool.destroy();
154955
- activeTranscoders--;
154956
- }
154957
- }
154958
-
154959
- /**
154960
- * @private
154961
- */
154962
- KTX2TextureTranscoder.BasisFormat = {
154963
- ETC1S: 0,
154964
- UASTC_4x4: 1
154965
- };
154966
-
154967
- /**
154968
- * @private
154969
- */
154970
- KTX2TextureTranscoder.TranscoderFormat = {
154971
- ETC1: 0,
154972
- ETC2: 1,
154973
- BC1: 2,
154974
- BC3: 3,
154975
- BC4: 4,
154976
- BC5: 5,
154977
- BC7_M6_OPAQUE_ONLY: 6,
154978
- BC7_M5: 7,
154979
- PVRTC1_4_RGB: 8,
154980
- PVRTC1_4_RGBA: 9,
154981
- ASTC_4x4: 10,
154982
- ATC_RGB: 11,
154983
- ATC_RGBA_INTERPOLATED_ALPHA: 12,
154984
- RGBA32: 13,
154985
- RGB565: 14,
154986
- BGR565: 15,
154987
- RGBA4444: 16
154988
- };
154989
-
154990
- /**
154991
- * @private
154992
- */
154993
- KTX2TextureTranscoder.EngineFormat = {
154994
- RGBAFormat: RGBAFormat,
154995
- RGBA_ASTC_4x4_Format: RGBA_ASTC_4x4_Format,
154996
- RGBA_BPTC_Format: RGBA_BPTC_Format,
154997
- RGBA_ETC2_EAC_Format: RGBA_ETC2_EAC_Format,
154998
- RGBA_PVRTC_4BPPV1_Format: RGBA_PVRTC_4BPPV1_Format,
154999
- RGBA_S3TC_DXT5_Format: RGBA_S3TC_DXT5_Format,
155000
- RGB_ETC1_Format: RGB_ETC1_Format,
155001
- RGB_ETC2_Format: RGB_ETC2_Format,
155002
- RGB_PVRTC_4BPPV1_Format: RGB_PVRTC_4BPPV1_Format,
155003
- RGB_S3TC_DXT1_Format: RGB_S3TC_DXT1_Format
155004
- };
155005
-
155006
- /* WEB WORKER */
155007
-
155008
- /**
155009
- * @private
155010
- * @constructor
155011
- */
155012
- KTX2TextureTranscoder.BasisWorker = function () {
155013
-
155014
- let config;
155015
- let transcoderPending;
155016
- let BasisModule;
155017
-
155018
- const EngineFormat = _EngineFormat; // eslint-disable-line no-undef
155019
- const TranscoderFormat = _TranscoderFormat; // eslint-disable-line no-undef
155020
- const BasisFormat = _BasisFormat; // eslint-disable-line no-undef
155021
-
155022
- self.addEventListener('message', function (e) {
155023
- const message = e.data;
155024
- switch (message.type) {
155025
- case 'init':
155026
- config = message.config;
155027
- init(message.transcoderBinary);
155028
- break;
155029
- case 'transcode':
155030
- transcoderPending.then(() => {
155031
- try {
155032
- const {
155033
- width,
155034
- height,
155035
- hasAlpha,
155036
- mipmaps,
155037
- format,
155038
- dfdTransferFn,
155039
- dfdFlags
155040
- } = transcode(message.buffers[0]);
155041
- const buffers = [];
155042
- for (let i = 0; i < mipmaps.length; ++i) {
155043
- buffers.push(mipmaps[i].data.buffer);
155044
- }
155045
- self.postMessage({
155046
- type: 'transcode',
155047
- id: message.id,
155048
- width,
155049
- height,
155050
- hasAlpha,
155051
- mipmaps,
155052
- format,
155053
- dfdTransferFn,
155054
- dfdFlags
155055
- }, buffers);
155056
- } catch (error) {
155057
- console.error(`[KTX2TextureTranscoder.BasisWorker]: ${error}`);
155058
- self.postMessage({type: 'error', id: message.id, error: error.message});
155059
- }
155060
- });
155061
- break;
155062
- }
155063
- });
155064
-
155065
- function init(wasmBinary) {
155066
- transcoderPending = new Promise(resolve => {
155067
- BasisModule = {
155068
- wasmBinary,
155069
- onRuntimeInitialized: resolve
155070
- };
155071
- BASIS(BasisModule); // eslint-disable-line no-undef
155072
- }).then(() => {
155073
- BasisModule.initializeBasis();
155074
- if (BasisModule.KTX2File === undefined) {
155075
- console.warn('KTX2TextureTranscoder: Please update Basis Universal transcoder.');
155076
- }
155077
- });
155078
- }
155079
-
155080
- function transcode(buffer) {
155081
- const ktx2File = new BasisModule.KTX2File(new Uint8Array(buffer));
155082
-
155083
- function cleanup() {
155084
- ktx2File.close();
155085
- ktx2File.delete();
155086
- }
155087
-
155088
- if (!ktx2File.isValid()) {
155089
- cleanup();
155090
- throw new Error('KTX2TextureTranscoder: Invalid or unsupported .ktx2 file');
155091
- }
155092
- const basisFormat = ktx2File.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S;
155093
- const width = ktx2File.getWidth();
155094
- const height = ktx2File.getHeight();
155095
- const levels = ktx2File.getLevels();
155096
- const hasAlpha = ktx2File.getHasAlpha();
155097
- const dfdTransferFn = ktx2File.getDFDTransferFunc();
155098
- const dfdFlags = ktx2File.getDFDFlags();
155099
- const {transcoderFormat, engineFormat} = getTranscoderFormat(basisFormat, width, height, hasAlpha);
155100
- if (!width || !height || !levels) {
155101
- cleanup();
155102
- throw new Error('KTX2TextureTranscoder: Invalid texture');
155103
- }
155104
- if (!ktx2File.startTranscoding()) {
155105
- cleanup();
155106
- throw new Error('KTX2TextureTranscoder: .startTranscoding failed');
155107
- }
155108
- const mipmaps = [];
155109
- for (let mip = 0; mip < levels; mip++) {
155110
- const levelInfo = ktx2File.getImageLevelInfo(mip, 0, 0);
155111
- const mipWidth = levelInfo.origWidth;
155112
- const mipHeight = levelInfo.origHeight;
155113
- const dst = new Uint8Array(ktx2File.getImageTranscodedSizeInBytes(mip, 0, 0, transcoderFormat));
155114
- const status = ktx2File.transcodeImage(dst, mip, 0, 0, transcoderFormat, 0, -1, -1);
155115
- if (!status) {
155116
- cleanup();
155117
- throw new Error('KTX2TextureTranscoder: .transcodeImage failed.');
155118
- }
155119
- mipmaps.push({data: dst, width: mipWidth, height: mipHeight});
155120
- }
155121
- cleanup();
155122
- return {width, height, hasAlpha, mipmaps, format: engineFormat, dfdTransferFn, dfdFlags};
155123
- }
155124
-
155125
- // Optimal choice of a transcoder target format depends on the Basis format (ETC1S or UASTC),
155126
- // device capabilities, and texture dimensions. The list below ranks the formats separately
155127
- // for ETC1S and UASTC.
155128
- //
155129
- // In some cases, transcoding UASTC to RGBA32 might be preferred for higher quality (at
155130
- // significant memory cost) compared to ETC1/2, BC1/3, and PVRTC. The transcoder currently
155131
- // chooses RGBA32 only as a last resort and does not expose that option to the caller.
155132
-
155133
- const FORMAT_OPTIONS = [{
155134
- if: 'astcSupported',
155135
- basisFormat: [BasisFormat.UASTC_4x4],
155136
- transcoderFormat: [TranscoderFormat.ASTC_4x4, TranscoderFormat.ASTC_4x4],
155137
- engineFormat: [EngineFormat.RGBA_ASTC_4x4_Format, EngineFormat.RGBA_ASTC_4x4_Format],
155138
- priorityETC1S: Infinity,
155139
- priorityUASTC: 1,
155140
- needsPowerOfTwo: false
155141
- }, {
155142
- if: 'bptcSupported',
155143
- basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
155144
- transcoderFormat: [TranscoderFormat.BC7_M5, TranscoderFormat.BC7_M5],
155145
- engineFormat: [EngineFormat.RGBA_BPTC_Format, EngineFormat.RGBA_BPTC_Format],
155146
- priorityETC1S: 3,
155147
- priorityUASTC: 2,
155148
- needsPowerOfTwo: false
155149
- }, {
155150
- if: 'dxtSupported',
155151
- basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
155152
- transcoderFormat: [TranscoderFormat.BC1, TranscoderFormat.BC3],
155153
- engineFormat: [EngineFormat.RGB_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format],
155154
- priorityETC1S: 4,
155155
- priorityUASTC: 5,
155156
- needsPowerOfTwo: false
155157
- }, {
155158
- if: 'etc2Supported',
155159
- basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
155160
- transcoderFormat: [TranscoderFormat.ETC1, TranscoderFormat.ETC2],
155161
- engineFormat: [EngineFormat.RGB_ETC2_Format, EngineFormat.RGBA_ETC2_EAC_Format],
155162
- priorityETC1S: 1,
155163
- priorityUASTC: 3,
155164
- needsPowerOfTwo: false
155165
- }, {
155166
- if: 'etc1Supported',
155167
- basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
155168
- transcoderFormat: [TranscoderFormat.ETC1],
155169
- engineFormat: [EngineFormat.RGB_ETC1_Format],
155170
- priorityETC1S: 2,
155171
- priorityUASTC: 4,
155172
- needsPowerOfTwo: false
155173
- }, {
155174
- if: 'pvrtcSupported',
155175
- basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
155176
- transcoderFormat: [TranscoderFormat.PVRTC1_4_RGB, TranscoderFormat.PVRTC1_4_RGBA],
155177
- engineFormat: [EngineFormat.RGB_PVRTC_4BPPV1_Format, EngineFormat.RGBA_PVRTC_4BPPV1_Format],
155178
- priorityETC1S: 5,
155179
- priorityUASTC: 6,
155180
- needsPowerOfTwo: true
155181
- }];
155182
- const ETC1S_OPTIONS = FORMAT_OPTIONS.sort(function (a, b) {
155183
- return a.priorityETC1S - b.priorityETC1S;
155184
- });
155185
- const UASTC_OPTIONS = FORMAT_OPTIONS.sort(function (a, b) {
155186
- return a.priorityUASTC - b.priorityUASTC;
155187
- });
155188
-
155189
- function getTranscoderFormat(basisFormat, width, height, hasAlpha) {
155190
- let transcoderFormat;
155191
- let engineFormat;
155192
- const options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS;
155193
- for (let i = 0; i < options.length; i++) {
155194
- const opt = options[i];
155195
- if (!config[opt.if]) continue;
155196
- if (!opt.basisFormat.includes(basisFormat)) continue;
155197
- if (hasAlpha && opt.transcoderFormat.length < 2) continue;
155198
- if (opt.needsPowerOfTwo && !(isPowerOfTwo(width) && isPowerOfTwo(height))) continue;
155199
- transcoderFormat = opt.transcoderFormat[hasAlpha ? 1 : 0];
155200
- engineFormat = opt.engineFormat[hasAlpha ? 1 : 0];
155201
- return {
155202
- transcoderFormat,
155203
- engineFormat
155204
- };
155205
- }
155206
- console.warn('KTX2TextureTranscoder: No suitable compressed texture format found. Decoding to RGBA32.');
155207
- transcoderFormat = TranscoderFormat.RGBA32;
155208
- engineFormat = EngineFormat.RGBAFormat;
155209
- return {
155210
- transcoderFormat,
155211
- engineFormat
155212
- };
155213
- }
155214
-
155215
- function isPowerOfTwo(value) {
155216
- if (value <= 2) return true;
155217
- return (value & value - 1) === 0 && value !== 0;
155218
- }
155219
- };
155220
-
155221
155265
  const screenPos = math.vec4();
155222
155266
  const viewPos = math.vec4();
155223
155267
 
@@ -161994,11 +162038,9 @@ class LASLoaderPlugin extends Plugin {
161994
162038
  try {
161995
162039
  parse$3(arrayBuffer, LASLoader, options).then((parsedData) => {
161996
162040
 
161997
- const loaderData = parsedData.loaderData;
161998
- const loaderDataHeader = loaderData.header;
161999
- const pointsFormatId = loaderDataHeader.pointsFormatId;
162000
-
162001
162041
  const attributes = parsedData.attributes;
162042
+ const loaderData = parsedData.loaderData;
162043
+ const pointsFormatId = loaderData.pointsFormatId !== undefined ? loaderData.pointsFormatId : -1;
162002
162044
 
162003
162045
  if (!attributes.POSITION) {
162004
162046
  sceneModel.finalize();
@@ -163329,7 +163371,7 @@ class CityJSONLoaderPlugin extends Plugin {
163329
163371
 
163330
163372
  _parseGeometrySurfacesWithSharedMaterial(ctx, geometry, objectMaterial, meshIds) {
163331
163373
 
163332
- ctx.performanceModel;
163374
+ const sceneModel = ctx.sceneModel;
163333
163375
  const sharedIndices = [];
163334
163376
  const geometryCfg = {
163335
163377
  positions: [],
@@ -163375,7 +163417,7 @@ class CityJSONLoaderPlugin extends Plugin {
163375
163417
 
163376
163418
  const meshId = "" + ctx.nextId++;
163377
163419
 
163378
- performanceModel.createMesh({
163420
+ sceneModel.createMesh({
163379
163421
  id: meshId,
163380
163422
  primitive: "triangles",
163381
163423
  positions: geometryCfg.positions,
@@ -163536,4 +163578,4 @@ class CityJSONLoaderPlugin extends Plugin {
163536
163578
  }
163537
163579
  }
163538
163580
 
163539
- export { AlphaFormat, AmbientLight, AngleMeasurementsPlugin, AnnotationsPlugin, AxisGizmoPlugin, BCFViewpointsPlugin, BasicDepthPacking, ByteType, CameraMemento, CameraPath, CameraPathAnimation, CityJSONLoaderPlugin, ClampToEdgeWrapping, Component, Configs, ContextMenu, CubicBezierCurve, Curve, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DirLight, DistanceMeasurementsPlugin, EdgeMaterial, EmphasisMaterial, FastNavPlugin, FloatType, Fresnel, GLTFDefaultDataSource, GLTFLoaderPlugin, HalfFloatType, ImagePlane, IntType, KTX2TextureTranscoder, LASLoaderPlugin, LambertMaterial, LightMap, LinearEncoding, LinearFilter, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, Loader, LoadingManager, LocaleService, LuminanceAlphaFormat, LuminanceFormat, Map$1 as Map, Marker, Mesh, MetallicMaterial, MirroredRepeatWrapping, ModelMemento, NavCubePlugin, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, Node$1 as Node, OBJLoaderPlugin, ObjectsMemento, Path, PerformanceModel, PhongMaterial, Plugin, PointLight, QuadraticBezierCurve, Queue, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, ReadableGeometry, RedFormat, RedIntegerFormat, ReflectionMap, RepeatWrapping, STLDefaultDataSource, STLLoaderPlugin, SceneModel, SectionPlane, SectionPlanesPlugin, ShortType, Skybox, SkyboxesPlugin, SpecularMaterial, SplineCurve, SpriteMarker, StoreyViewsPlugin, Texture, TextureTranscoder, TreeViewPlugin, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VBOGeometry, VBOSceneModel, ViewCullPlugin, Viewer, WebIFCLoaderPlugin, WorkerPool, XKTDefaultDataSource, XKTLoaderPlugin, XML3DLoaderPlugin, _SRGBAFormat, buildBoxGeometry, buildBoxLinesGeometry, buildCylinderGeometry, buildGridGeometry, buildPlaneGeometry, buildSphereGeometry, buildTorusGeometry, buildVectorTextGeometry, load3DSGeometry, loadOBJGeometry, math, sRGBEncoding, stats, utils };
163581
+ export { AlphaFormat, AmbientLight, AngleMeasurementsPlugin, AnnotationsPlugin, AxisGizmoPlugin, BCFViewpointsPlugin, BasicDepthPacking, ByteType, CameraMemento, CameraPath, CameraPathAnimation, CityJSONLoaderPlugin, ClampToEdgeWrapping, Component, Configs, ContextMenu, CubicBezierCurve, Curve, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DirLight, DistanceMeasurementsPlugin, EdgeMaterial, EmphasisMaterial, FastNavPlugin, FloatType, Fresnel, GLTFDefaultDataSource, GLTFLoaderPlugin, HalfFloatType, ImagePlane, IntType, KTX2TextureTranscoder, LASLoaderPlugin, LambertMaterial, LightMap, LinearEncoding, LinearFilter, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, Loader, LoadingManager, LocaleService, LuminanceAlphaFormat, LuminanceFormat, Map$1 as Map, Marker, Mesh, MetallicMaterial, MirroredRepeatWrapping, ModelMemento, NavCubePlugin, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, Node$1 as Node, OBJLoaderPlugin, ObjectsMemento, Path, PerformanceModel, PhongMaterial, Plugin, PointLight, QuadraticBezierCurve, Queue, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBFormat, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, ReadableGeometry, RedFormat, RedIntegerFormat, ReflectionMap, RepeatWrapping, STLDefaultDataSource, STLLoaderPlugin, SceneModel, SectionPlane, SectionPlanesPlugin, ShortType, Skybox, SkyboxesPlugin, SpecularMaterial, SplineCurve, SpriteMarker, StoreyViewsPlugin, Texture, TextureTranscoder, TreeViewPlugin, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VBOGeometry, VBOSceneModel, ViewCullPlugin, Viewer, WebIFCLoaderPlugin, WorkerPool$1 as WorkerPool, XKTDefaultDataSource, XKTLoaderPlugin, XML3DLoaderPlugin, _SRGBAFormat, buildBoxGeometry, buildBoxLinesGeometry, buildCylinderGeometry, buildGridGeometry, buildPlaneGeometry, buildSphereGeometry, buildTorusGeometry, buildVectorTextGeometry, getKTX2TextureTranscoder, load3DSGeometry, loadOBJGeometry, math, sRGBEncoding, stats, utils };