diff --git a/Apps/SampleData/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx b/Apps/SampleData/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx
deleted file mode 100644
index 7a8880d04115..000000000000
Binary files a/Apps/SampleData/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx and /dev/null differ
diff --git a/Apps/SampleData/models/CesiumBalloonKTX2/CesiumBalloonKTX2.glb b/Apps/SampleData/models/CesiumBalloonKTX2/CesiumBalloonKTX2.glb
new file mode 100644
index 000000000000..4b7580f05979
Binary files /dev/null and b/Apps/SampleData/models/CesiumBalloonKTX2/CesiumBalloonKTX2.glb differ
diff --git a/Apps/Sandcastle/gallery/3D Models.html b/Apps/Sandcastle/gallery/3D Models.html
index 3172c1023b00..deed91a406ce 100644
--- a/Apps/Sandcastle/gallery/3D Models.html
+++ b/Apps/Sandcastle/gallery/3D Models.html
@@ -133,6 +133,20 @@
);
},
},
+ {
+ text: "KTX2 Compressed Balloon",
+ onselect: function () {
+ if (!Cesium.FeatureDetection.supportsBasis(viewer.scene)) {
+ window.alert(
+ "This browser does not support Basis Universal compressed textures"
+ );
+ }
+ createModel(
+ "../../SampleData/models/CesiumBalloonKTX2/CesiumBalloonKTX2.glb",
+ 1000.0
+ );
+ },
+ },
];
Sandcastle.addToolbarMenu(options);
diff --git a/Apps/Sandcastle/gallery/Image-Based Lighting.html b/Apps/Sandcastle/gallery/Image-Based Lighting.html
index f689badbd417..8155119d9201 100644
--- a/Apps/Sandcastle/gallery/Image-Based Lighting.html
+++ b/Apps/Sandcastle/gallery/Image-Based Lighting.html
@@ -66,58 +66,62 @@
}
var environmentMapURL =
- "https://cesium.com/public/SandcastleSampleData/kiara_6_afternoon_2k_ibl.ktx";
+ "https://cesium.com/public/SandcastleSampleData/kiara_6_afternoon_2k_ibl.ktx2";
var modelURL = "../../SampleData/models/Pawns/Pawns.glb";
- // This environment map was processed using Google's Filament project. To process your own:
+ // This environment map was processed using Khronos's glTF IBL Sampler. To process your own:
+ // 1 - Download and build the Khronos glTF IBL Sampler (https://github.com/KhronosGroup/glTF-IBL-Sampler).
+ // 2 - Run `cli -inputPath /path/to/image.hdr -outCubeMap /path/to/output.ktx2`. Run `cli -h` for all options.
+
+ // To generate the spherical harmonic coefficients below, use Google's Filament project:
// 1 - Download the Filament release (https://github.com/google/filament/releases).
// 2 - Run `cmgen --type=ktx --deploy=/path/to/output /path/to/image.hdr`. Other formats are also supported. Run `cmgen --help` for all options.
- // 3 - Take the generated coefficients and the KTX file and load them in CesiumJS as shown below.
+ // 3 - Take the generated coefficients and load them in CesiumJS as shown below.
var L00 = new Cesium.Cartesian3(
- 0.170455150831422,
- 0.163151083190219,
- 0.196966760289763
+ 1.234709620475769,
+ 1.221461296081543,
+ 1.273156881332397
);
var L1_1 = new Cesium.Cartesian3(
- -0.066550267689383,
- -0.022088055746048,
- 0.078835009246127
+ 1.135921120643616,
+ 1.171217799186707,
+ 1.287644743919373
);
var L10 = new Cesium.Cartesian3(
- 0.038364097478591,
- 0.045714300098753,
- 0.063498904606215
+ 1.245193719863892,
+ 1.245591878890991,
+ 1.282818794250488
);
var L11 = new Cesium.Cartesian3(
- -0.01436536331281,
- -0.026490613715151,
- -0.05018940406602
+ -1.106930732727051,
+ -1.112522482872009,
+ -1.153198838233948
);
var L2_2 = new Cesium.Cartesian3(
- -0.05153278691789,
- -0.050777795729986,
- -0.056449044453032
+ -1.086226940155029,
+ -1.079731941223145,
+ -1.101912498474121
);
var L2_1 = new Cesium.Cartesian3(
- 0.043454596136534,
- 0.046672590104157,
- 0.05753010764661
+ 1.189834713935852,
+ 1.185906887054443,
+ 1.214385271072388
);
var L20 = new Cesium.Cartesian3(
- -0.00164046627411,
- 0.001286638231156,
- 0.007228908989616
+ 0.01778045296669,
+ 0.02013735473156,
+ 0.025313569232821
);
var L21 = new Cesium.Cartesian3(
- -0.042260855700641,
- -0.046394335094707,
- -0.057562936365585
+ -1.086826920509338,
+ -1.084611177444458,
+ -1.111204028129578
);
var L22 = new Cesium.Cartesian3(
- -0.004953478914091,
- -0.000479681664876,
- 0.008508150106928
+ -0.05241484940052,
+ -0.048303380608559,
+ -0.041960217058659
);
var coefficients = [L00, L1_1, L10, L11, L2_2, L2_1, L20, L21, L22];
diff --git a/Apps/Sandcastle/gallery/Materials.html b/Apps/Sandcastle/gallery/Materials.html
index ff2071f62b6f..90c6d5ca053c 100644
--- a/Apps/Sandcastle/gallery/Materials.html
+++ b/Apps/Sandcastle/gallery/Materials.html
@@ -218,17 +218,25 @@
});
}
- function applyCompressedTextureMaterial(primitive, scene) {
- Sandcastle.declare(applyCompressedTextureMaterial); // For highlighting in Sandcastle.
-
- var compressedImageUrl;
- if (scene.getCompressedTextureFormatSupported("s3tc")) {
- compressedImageUrl = "../images/LogoDXT1.ktx";
- } else if (scene.getCompressedTextureFormatSupported("etc1")) {
- compressedImageUrl = "../images/LogoETC1.ktx";
- } else if (scene.getCompressedTextureFormatSupported("pvrtc")) {
- compressedImageUrl = "../images/LogoPVR.ktx";
- }
+ function applyETC1SCompressedTextureMaterial(primitive, scene) {
+ Sandcastle.declare(applyETC1SCompressedTextureMaterial); // For highlighting in Sandcastle.
+
+ var compressedImageUrl = "../images/Cesium_Logo_ETC1S.ktx2";
+
+ primitive.appearance.material = new Cesium.Material({
+ fabric: {
+ type: "Image",
+ uniforms: {
+ image: compressedImageUrl,
+ },
+ },
+ });
+ }
+
+ function applyUASTCCompressedTextureMaterial(primitive, scene) {
+ Sandcastle.declare(applyUASTCCompressedTextureMaterial); // For highlighting in Sandcastle.
+
+ var compressedImageUrl = "../images/Cesium_Logo_UASTC.ktx2";
primitive.appearance.material = new Cesium.Material({
fabric: {
@@ -357,11 +365,29 @@
},
},
{
- text: "Compressed Image",
+ text: "ETC1S Compressed Image",
+ onselect: function () {
+ if (!Cesium.FeatureDetection.supportsBasis(scene)) {
+ window.alert(
+ "This browser does not support Basis Universal compressed textures"
+ );
+ }
+ toggleRectangleVisibility();
+ applyETC1SCompressedTextureMaterial(rectangle, scene);
+ Sandcastle.highlight(applyETC1SCompressedTextureMaterial);
+ },
+ },
+ {
+ text: "UASTC Compressed Image",
onselect: function () {
+ if (!Cesium.FeatureDetection.supportsBasis(scene)) {
+ window.alert(
+ "This browser does not support Basis Universal compressed textures"
+ );
+ }
toggleRectangleVisibility();
- applyCompressedTextureMaterial(rectangle, scene);
- Sandcastle.highlight(applyCompressedTextureMaterial);
+ applyUASTCCompressedTextureMaterial(rectangle, scene);
+ Sandcastle.highlight(applyUASTCCompressedTextureMaterial);
},
},
]);
diff --git a/Apps/Sandcastle/images/Cesium_Logo_ETC1S.ktx2 b/Apps/Sandcastle/images/Cesium_Logo_ETC1S.ktx2
new file mode 100644
index 000000000000..1c44a7e3925b
Binary files /dev/null and b/Apps/Sandcastle/images/Cesium_Logo_ETC1S.ktx2 differ
diff --git a/Apps/Sandcastle/images/Cesium_Logo_UASTC.ktx2 b/Apps/Sandcastle/images/Cesium_Logo_UASTC.ktx2
new file mode 100644
index 000000000000..53ccb13613e1
Binary files /dev/null and b/Apps/Sandcastle/images/Cesium_Logo_UASTC.ktx2 differ
diff --git a/Apps/Sandcastle/images/LogoDXT1.ktx b/Apps/Sandcastle/images/LogoDXT1.ktx
deleted file mode 100644
index 73598d1c8d30..000000000000
Binary files a/Apps/Sandcastle/images/LogoDXT1.ktx and /dev/null differ
diff --git a/Apps/Sandcastle/images/LogoETC1.ktx b/Apps/Sandcastle/images/LogoETC1.ktx
deleted file mode 100644
index 9d8b88d7f541..000000000000
Binary files a/Apps/Sandcastle/images/LogoETC1.ktx and /dev/null differ
diff --git a/Apps/Sandcastle/images/LogoPVR.ktx b/Apps/Sandcastle/images/LogoPVR.ktx
deleted file mode 100644
index fd3461c7bbbb..000000000000
Binary files a/Apps/Sandcastle/images/LogoPVR.ktx and /dev/null differ
diff --git a/CHANGES.md b/CHANGES.md
index a10a23460c42..b260f8299184 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,6 +2,10 @@
### 1.83 - 2021-07-01
+##### Breaking Changes :mega:
+
+- Dropped support for KTX1 and Crunch textures; use the [`ktx2ktx2`](https://github.com/KhronosGroup/KTX-Software) converter tool to update existing KTX1 files.
+
##### Additions :tada:
- Added dynamic terrain exaggeration with `Globe.terrainExaggeration` and `Globe.terrainExaggerationRelativeHeight`. [#9603](https://github.com/CesiumGS/cesium/pull/9603)
@@ -10,6 +14,11 @@
- Added checks for supported 3D Tiles extensions. [#9552](https://github.com/CesiumGS/cesium/issues/9552)
- Added documentation clarifying that the `outlineWidth` property will be ignored on all major browsers on Windows platforms. [#9600](https://github.com/CesiumGS/cesium/pull/9600)
- Added documentation for `KmlTour`, `KmlTourFlyTo`, and `KmlTourWait`. Added documentation and a `kmlTours` getter to `KmlDataSource`. Removed references to `KmlTourSoundCues`. [#8073](https://github.com/CesiumGS/cesium/issues/8073)
+- Added support for KTX2 and Basis Universal compressed textures. [#9513](https://github.com/CesiumGS/cesium/issues/9513)
+ - Added support for glTF models with the [`KHR_texture_basisu`](https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_texture_basisu/README.md) extension.
+ - Added support for 8-bit, 16-bit float, and 32-bit float KTX2 specular environment maps.
+ - Added support for KTX2 images in `Material`.
+ - Added new `PixelFormat` and `WebGLConstants` enums from WebGL extensions `WEBGL_compressed_texture_etc`, `WEBGL_compressed_texture_astc`, and `EXT_texture_compression_bptc`.
- Added the ability to hide outlines on OSM Buildings and other tilesets and glTF models using the CESIUM_primitive_outline extension. [#8959](https://github.com/CesiumGS/cesium/issues/8959)
- Added option to ignore extraneous colorspace information in glTF textures and `ImageBitmap`. [#9624](https://github.com/CesiumGS/cesium/pull/9624)
diff --git a/LICENSE.md b/LICENSE.md
index f12698a068b7..1041d7c1bd95 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -556,58 +556,47 @@ https://github.com/mourner/quickselect
> TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
> THIS SOFTWARE.
-### crunch
+### basis_universal
-https://github.com/BinomialLLC/crunch
+https://github.com/BinomialLLC/basis_universal
-> crunch/crnlib uses the ZLIB license:
-> http://opensource.org/licenses/Zlib
->
-> Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC
->
-> This software is provided 'as-is', without any express or implied
-> warranty. In no event will the authors be held liable for any damages
-> arising from the use of this software.
->
-> Permission is granted to anyone to use this software for any purpose,
-> including commercial applications, and to alter it and redistribute it
-> freely, subject to the following restrictions:
->
-> 1. The origin of this software must not be misrepresented; you must not
-> claim that you wrote the original software. If you use this software
-> in a product, an acknowledgment in the product documentation would be
-> appreciated but is not required.
+> Licensed under the Apache License, Version 2.0 (the "License"); you may not
+> use this file except in compliance with the License. You may obtain a copy of
+> the License at
>
-> 2. Altered source versions must be plainly marked as such, and must not be
-> misrepresented as being the original software.
+>
- * The following are part of the KTX format specification but are not supported:
- * request.throttle
is true and the request does not have high enough priority.
- *
- * @exception {RuntimeError} Unsupported compressed format.
- *
- * @example
- * // load a single URL asynchronously
- * Cesium.loadCRN('some/url').then(function(textureData) {
- * var width = textureData.width;
- * var height = textureData.height;
- * var format = textureData.internalFormat;
- * var arrayBufferView = textureData.bufferView;
- * // use the data to create a texture
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link https://github.com/BinomialLLC/crunch|crunch DXTc texture compression and transcoding library}
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- * @deprecated This function has been deprecated and will be removed in CesiumJS 1.83.
- */
-function loadCRN(resourceOrUrlOrBuffer) {
- deprecationWarning(
- "loadCRN",
- "loadCRN is deprecated and will be removed in CesiumJS 1.83."
- );
- //>>includeStart('debug', pragmas.debug);
- if (!defined(resourceOrUrlOrBuffer)) {
- throw new DeveloperError("resourceOrUrlOrBuffer is required.");
- }
- //>>includeEnd('debug');
-
- var loadPromise;
- if (
- resourceOrUrlOrBuffer instanceof ArrayBuffer ||
- ArrayBuffer.isView(resourceOrUrlOrBuffer)
- ) {
- loadPromise = when.resolve(resourceOrUrlOrBuffer);
- } else {
- var resource = Resource.createIfNeeded(resourceOrUrlOrBuffer);
- loadPromise = resource.fetchArrayBuffer();
- }
-
- if (!defined(loadPromise)) {
- return undefined;
- }
-
- return loadPromise
- .then(function (data) {
- if (!defined(data)) {
- return;
- }
- var transferrableObjects = [];
- if (data instanceof ArrayBuffer) {
- transferrableObjects.push(data);
- } else if (
- data.byteOffset === 0 &&
- data.byteLength === data.buffer.byteLength
- ) {
- transferrableObjects.push(data.buffer);
- } else {
- // data is a view of an array buffer. need to copy so it is transferrable to web worker
- data = data.slice(0, data.length);
- transferrableObjects.push(data.buffer);
- }
-
- return transcodeTaskProcessor.scheduleTask(data, transferrableObjects);
- })
- .then(function (compressedTextureBuffer) {
- return CompressedTextureBuffer.clone(compressedTextureBuffer);
- });
-}
-export default loadCRN;
diff --git a/Source/Core/loadKTX.js b/Source/Core/loadKTX.js
deleted file mode 100644
index e3905f01573f..000000000000
--- a/Source/Core/loadKTX.js
+++ /dev/null
@@ -1,280 +0,0 @@
-import when from "../ThirdParty/when.js";
-import Check from "./Check.js";
-import CompressedTextureBuffer from "./CompressedTextureBuffer.js";
-import defined from "./defined.js";
-import PixelFormat from "./PixelFormat.js";
-import Resource from "./Resource.js";
-import RuntimeError from "./RuntimeError.js";
-import WebGLConstants from "./WebGLConstants.js";
-import deprecationWarning from "./deprecationWarning.js";
-
-/**
- * Asynchronously loads and parses the given URL to a KTX file or parses the raw binary data of a KTX file.
- * Returns a promise that will resolve to an object containing the image buffer, width, height and format once loaded,
- * or reject if the URL failed to load or failed to parse the data. The data is loaded
- * using XMLHttpRequest, which means that in order to make requests to another origin,
- * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.
- *
- *
- *
request.throttle
is true and the request does not have high enough priority.
- *
- * @exception {RuntimeError} Invalid KTX file.
- * @exception {RuntimeError} File is the wrong endianness.
- * @exception {RuntimeError} glInternalFormat is not a valid format.
- * @exception {RuntimeError} glType must be zero when the texture is compressed.
- * @exception {RuntimeError} The type size for compressed textures must be 1.
- * @exception {RuntimeError} glFormat must be zero when the texture is compressed.
- * @exception {RuntimeError} Generating mipmaps for a compressed texture is unsupported.
- * @exception {RuntimeError} The base internal format must be the same as the format for uncompressed textures.
- * @exception {RuntimeError} 3D textures are not supported.
- * @exception {RuntimeError} Texture arrays are not supported.
- * @exception {RuntimeError} Cubemaps are not supported.
- *
- * @example
- * // load a single URL asynchronously
- * Cesium.loadKTX('some/url').then(function(ktxData) {
- * var width = ktxData.width;
- * var height = ktxData.height;
- * var format = ktxData.internalFormat;
- * var arrayBufferView = ktxData.bufferView;
- * // use the data to create a texture
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/|KTX file format}
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- * @deprecated This function has been deprecated and will be removed in CesiumJS 1.83.
- */
-function loadKTX(resourceOrUrlOrBuffer) {
- deprecationWarning(
- "loadKTX",
- "loadKTX is deprecated and will be removed in CesiumJS 1.83."
- );
- //>>includeStart('debug', pragmas.debug);
- Check.defined("resourceOrUrlOrBuffer", resourceOrUrlOrBuffer);
- //>>includeEnd('debug');
-
- var loadPromise;
- if (
- resourceOrUrlOrBuffer instanceof ArrayBuffer ||
- ArrayBuffer.isView(resourceOrUrlOrBuffer)
- ) {
- loadPromise = when.resolve(resourceOrUrlOrBuffer);
- } else {
- var resource = Resource.createIfNeeded(resourceOrUrlOrBuffer);
- loadPromise = resource.fetchArrayBuffer();
- }
-
- if (!defined(loadPromise)) {
- return undefined;
- }
-
- return loadPromise.then(function (data) {
- if (defined(data)) {
- return parseKTX(data);
- }
- });
-}
-
-var fileIdentifier = [
- 0xab,
- 0x4b,
- 0x54,
- 0x58,
- 0x20,
- 0x31,
- 0x31,
- 0xbb,
- 0x0d,
- 0x0a,
- 0x1a,
- 0x0a,
-];
-var endiannessTest = 0x04030201;
-var faceOrder = [
- "positiveX",
- "negativeX",
- "positiveY",
- "negativeY",
- "positiveZ",
- "negativeZ",
-];
-
-var sizeOfUint32 = 4;
-
-function parseKTX(data) {
- var byteBuffer = new Uint8Array(data);
-
- var isKTX = true;
- var i;
- for (i = 0; i < fileIdentifier.length; ++i) {
- if (fileIdentifier[i] !== byteBuffer[i]) {
- isKTX = false;
- break;
- }
- }
-
- if (!isKTX) {
- throw new RuntimeError("Invalid KTX file.");
- }
-
- var view;
- var byteOffset;
-
- if (defined(data.buffer)) {
- view = new DataView(data.buffer);
- byteOffset = data.byteOffset;
- } else {
- view = new DataView(data);
- byteOffset = 0;
- }
-
- byteOffset += 12; // skip identifier
-
- var endianness = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- if (endianness !== endiannessTest) {
- throw new RuntimeError("File is the wrong endianness.");
- }
-
- var glType = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- var glTypeSize = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- var glFormat = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- var glInternalFormat = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- var glBaseInternalFormat = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- var pixelWidth = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- var pixelHeight = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- var pixelDepth = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- var numberOfArrayElements = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- var numberOfFaces = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- var numberOfMipmapLevels = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
- var bytesOfKeyValueByteSize = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
-
- // skip metadata
- byteOffset += bytesOfKeyValueByteSize;
-
- var imageSize = view.getUint32(byteOffset, true);
- byteOffset += sizeOfUint32;
-
- var texture;
- if (defined(data.buffer)) {
- texture = new Uint8Array(data.buffer, byteOffset, imageSize);
- } else {
- texture = new Uint8Array(data, byteOffset, imageSize);
- }
-
- // Some tools use a sized internal format.
- // See table 2: https://www.opengl.org/sdk/docs/man/html/glTexImage2D.xhtml
- if (glInternalFormat === WebGLConstants.RGB8) {
- glInternalFormat = PixelFormat.RGB;
- } else if (glInternalFormat === WebGLConstants.RGBA8) {
- glInternalFormat = PixelFormat.RGBA;
- }
-
- if (!PixelFormat.validate(glInternalFormat)) {
- throw new RuntimeError("glInternalFormat is not a valid format.");
- }
-
- if (PixelFormat.isCompressedFormat(glInternalFormat)) {
- if (glType !== 0) {
- throw new RuntimeError(
- "glType must be zero when the texture is compressed."
- );
- }
- if (glTypeSize !== 1) {
- throw new RuntimeError(
- "The type size for compressed textures must be 1."
- );
- }
- if (glFormat !== 0) {
- throw new RuntimeError(
- "glFormat must be zero when the texture is compressed."
- );
- }
- } else if (glType !== WebGLConstants.UNSIGNED_BYTE) {
- throw new RuntimeError("Only unsigned byte buffers are supported.");
- } else if (glBaseInternalFormat !== glFormat) {
- throw new RuntimeError(
- "The base internal format must be the same as the format for uncompressed textures."
- );
- }
-
- if (pixelDepth !== 0) {
- throw new RuntimeError("3D textures are unsupported.");
- }
-
- if (numberOfArrayElements !== 0) {
- throw new RuntimeError("Texture arrays are unsupported.");
- }
-
- var offset = texture.byteOffset;
- var mipmaps = new Array(numberOfMipmapLevels);
- for (i = 0; i < numberOfMipmapLevels; ++i) {
- var level = (mipmaps[i] = {});
- for (var j = 0; j < numberOfFaces; ++j) {
- var width = pixelWidth >> i;
- var height = pixelHeight >> i;
- var levelSize = PixelFormat.isCompressedFormat(glInternalFormat)
- ? PixelFormat.compressedTextureSizeInBytes(
- glInternalFormat,
- width,
- height
- )
- : PixelFormat.textureSizeInBytes(
- glInternalFormat,
- glType,
- width,
- height
- );
- var levelBuffer = new Uint8Array(texture.buffer, offset, levelSize);
- level[faceOrder[j]] = new CompressedTextureBuffer(
- glInternalFormat,
- width,
- height,
- levelBuffer
- );
- offset += levelSize;
- }
- offset += 3 - ((offset + 3) % 4) + 4;
- }
-
- var result = mipmaps;
- if (numberOfFaces === 1) {
- for (i = 0; i < numberOfMipmapLevels; ++i) {
- result[i] = result[i][faceOrder[0]];
- }
- }
- if (numberOfMipmapLevels === 1) {
- result = result[0];
- }
-
- return result;
-}
-export default loadKTX;
diff --git a/Source/Core/loadKTX2.js b/Source/Core/loadKTX2.js
new file mode 100644
index 000000000000..9c0f67379787
--- /dev/null
+++ b/Source/Core/loadKTX2.js
@@ -0,0 +1,105 @@
+import Check from "./Check.js";
+import Resource from "./Resource.js";
+import KTX2Transcoder from "./KTX2Transcoder.js";
+import when from "../ThirdParty/when.js";
+
+/**
+ * Stores the supported formats that KTX2 can transcode to. Called during context creation.
+ *
+ * @param {Boolean} s3tc Whether or not S3TC is supported
+ * @param {Boolean} pvrtc Whether or not PVRTC is supported
+ * @param {Boolean} astc Whether or not ASTC is supported
+ * @param {Boolean} etc Whether or not ETC is supported
+ * @param {Boolean} etc1 Whether or not ETC1 is supported
+ * @param {Boolean} bc7 Whether or not BC7 is supported
+ * @private
+ */
+var supportedTranscoderFormats;
+
+loadKTX2.setKTX2SupportedFormats = function (
+ s3tc,
+ pvrtc,
+ astc,
+ etc,
+ etc1,
+ bc7
+) {
+ supportedTranscoderFormats = {
+ s3tc: s3tc,
+ pvrtc: pvrtc,
+ astc: astc,
+ etc: etc,
+ etc1: etc1,
+ bc7: bc7,
+ };
+};
+
+/**
+ * Asynchronously loads and parses the given URL to a KTX2 file or parses the raw binary data of a KTX2 file.
+ * Returns a promise that will resolve to an object containing the image buffer, width, height, and format once loaded,
+ * or reject if the URL failed to load or failed to parse the data. The data is loaded
+ * using XMLHttpRequest, which means that in order to make requests to another origin,
+ * the server must have Cross-Origin Resource sharing (CORS) headers enabled.
+ * + * The following are part of the KTX2 format specification but are not supported: + *
request.throttle
is true and the request does not have high enough priority.
+ *
+ * @exception {RuntimeError} Invalid KTX2 file.
+ * @exception {RuntimeError} KTX2 texture arrays are not supported.
+ * @exception {RuntimeError} KTX2 3D textures are unsupported.
+ * @exception {RuntimeError} No transcoding format target available for ETC1S compressed ktx2s.
+ * @exception {RuntimeError} No transcoding format target available for UASTC compressed ktx2s.
+ * @exception {RuntimeError} startTranscoding() failed.
+ * @exception {RuntimeError} transcodeImage() failed.
+ *
+ * @example
+ * // load a single URL asynchronously
+ * Cesium.loadKTX2('some/url').then(function (ktx2Data) {
+ * var width = ktx2Data.width;
+ * var height = ktx2Data.height;
+ * var format = ktx2Data.internalFormat;
+ * var arrayBufferView = ktx2Data.bufferView;
+ * // use the data to create a texture
+ * }).otherwise(function (error) {
+ * // an error occurred.
+ * });
+ *
+ * @see {@link https://github.com/KhronosGroup/KTX-Specification|KTX file format}
+ * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
+ * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
+ * @private
+ */
+function loadKTX2(resourceOrUrlOrBuffer) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.defined("resourceOrUrlOrBuffer", resourceOrUrlOrBuffer);
+ //>>includeEnd('debug');
+
+ var loadPromise;
+ if (
+ resourceOrUrlOrBuffer instanceof ArrayBuffer ||
+ ArrayBuffer.isView(resourceOrUrlOrBuffer)
+ ) {
+ loadPromise = when.resolve(resourceOrUrlOrBuffer);
+ } else {
+ var resource = Resource.createIfNeeded(resourceOrUrlOrBuffer);
+ loadPromise = resource.fetchArrayBuffer();
+ }
+
+ // load module then return
+ return loadPromise.then(function (data) {
+ return KTX2Transcoder.transcode(data, supportedTranscoderFormats);
+ });
+}
+
+export default loadKTX2;
diff --git a/Source/Core/parseKTX2.js b/Source/Core/parseKTX2.js
new file mode 100644
index 000000000000..6ee2eff26fe5
--- /dev/null
+++ b/Source/Core/parseKTX2.js
@@ -0,0 +1,293 @@
+import Check from "./Check.js";
+import defined from "./defined.js";
+import PixelFormat from "./PixelFormat.js";
+import RuntimeError from "./RuntimeError.js";
+import VulkanConstants from "./VulkanConstants.js";
+import PixelDatatype from "../Renderer/PixelDatatype.js";
+import { read } from "../ThirdParty/Workers/ktx-parse.modern.js";
+
+var faceOrder = [
+ "positiveX",
+ "negativeX",
+ "positiveY",
+ "negativeY",
+ "positiveZ",
+ "negativeZ",
+];
+
+// Flags
+var colorModelETC1S = 163;
+var colorModelUASTC = 166;
+
+/**
+ * Parses and transcodes KTX2 buffers to an appropriate target format.
+ *
+ * @param {Uint8Array} data Data representing one KTX2 texture.
+ * @param {Object} supportedTargetFormats Target formats available on the current system.
+ * @param {Object} transcoderModule basis_transcoder object.
+ *
+ * @private
+ */
+function parseKTX2(
+ data,
+ supportedTargetFormats,
+ transcoderModule,
+ transferableObjects
+) {
+ //>>includeStart('debug', pragmas.debug);
+ Check.typeOf.object("transcoderModule", transcoderModule);
+ //>>includeEnd('debug');
+
+ var header;
+ try {
+ header = read(data);
+ } catch (e) {
+ throw new RuntimeError("Invalid KTX2 file.");
+ }
+
+ if (header.layerCount !== 0) {
+ throw new RuntimeError("KTX2 texture arrays are not supported.");
+ }
+
+ if (header.pixelDepth !== 0) {
+ throw new RuntimeError("KTX2 3D textures are unsupported.");
+ }
+
+ var dfd = header.dataFormatDescriptor[0];
+ var result = new Array(header.levelCount);
+
+ if (
+ header.vkFormat === 0x0 &&
+ (dfd.colorModel === colorModelETC1S || dfd.colorModel === colorModelUASTC)
+ ) {
+ // Compressed, initialize transcoder module
+ transcodeCompressed(
+ data,
+ header,
+ supportedTargetFormats,
+ transcoderModule,
+ transferableObjects,
+ result
+ );
+ } else {
+ transferableObjects.push(data.buffer);
+ parseUncompressed(header, result);
+ }
+
+ return result;
+}
+
+// Parser for uncompressed
+function parseUncompressed(header, result) {
+ var internalFormat =
+ header.vkFormat === VulkanConstants.VK_FORMAT_R8G8B8_SRGB
+ ? PixelFormat.RGB
+ : PixelFormat.RGBA;
+ var datatype;
+ if (header.vkFormat === VulkanConstants.VK_FORMAT_R8G8B8A8_UNORM) {
+ datatype = PixelDatatype.UNSIGNED_BYTE;
+ } else if (
+ header.vkFormat === VulkanConstants.VK_FORMAT_R16G16B16A16_SFLOAT
+ ) {
+ datatype = PixelDatatype.HALF_FLOAT;
+ } else if (
+ header.vkFormat === VulkanConstants.VK_FORMAT_R32G32B32A32_SFLOAT
+ ) {
+ datatype = PixelDatatype.FLOAT;
+ }
+
+ for (var i = 0; i < header.levels.length; ++i) {
+ var level = {};
+ result[i] = level;
+ var levelBuffer = header.levels[i].levelData;
+
+ var width = header.pixelWidth >> i;
+ var height = header.pixelHeight >> i;
+ var faceLength =
+ width * height * PixelFormat.componentsLength(internalFormat);
+
+ for (var j = 0; j < header.faceCount; ++j) {
+ // multiply levelBuffer.byteOffset by the size in bytes of the pixel data type
+ var faceByteOffset =
+ levelBuffer.byteOffset + faceLength * header.typeSize * j;
+ var faceView;
+ if (!defined(datatype) || PixelDatatype.sizeInBytes(datatype) === 1) {
+ faceView = new Uint8Array(
+ levelBuffer.buffer,
+ faceByteOffset,
+ faceLength
+ );
+ } else if (PixelDatatype.sizeInBytes(datatype) === 2) {
+ faceView = new Uint16Array(
+ levelBuffer.buffer,
+ faceByteOffset,
+ faceLength
+ );
+ } else {
+ faceView = new Float32Array(
+ levelBuffer.buffer,
+ faceByteOffset,
+ faceLength
+ );
+ }
+
+ level[faceOrder[j]] = {
+ internalFormat: internalFormat,
+ datatype: datatype,
+ width: width,
+ height: height,
+ levelBuffer: faceView,
+ };
+ }
+ }
+}
+
+function transcodeCompressed(
+ data,
+ header,
+ supportedTargetFormats,
+ transcoderModule,
+ transferableObjects,
+ result
+) {
+ var ktx2File = new transcoderModule.KTX2File(data);
+ var width = ktx2File.getWidth();
+ var height = ktx2File.getHeight();
+ var levels = ktx2File.getLevels();
+ var hasAlpha = ktx2File.getHasAlpha();
+
+ if (!(width > 0) || !(height > 0) || !(levels > 0)) {
+ ktx2File.close();
+ ktx2File.delete();
+ throw new RuntimeError("Invalid KTX2 file");
+ }
+
+ var internalFormat, transcoderFormat;
+ var dfd = header.dataFormatDescriptor[0];
+ var BasisFormat = transcoderModule.transcoder_texture_format;
+
+ // Determine target format based on platform support
+ if (dfd.colorModel === colorModelETC1S) {
+ if (supportedTargetFormats.etc) {
+ internalFormat = hasAlpha
+ ? PixelFormat.RGBA8_ETC2_EAC
+ : PixelFormat.RGB8_ETC2;
+ transcoderFormat = hasAlpha
+ ? BasisFormat.cTFETC2_RGBA
+ : BasisFormat.cTFETC1_RGB;
+ } else if (supportedTargetFormats.etc1 && !hasAlpha) {
+ internalFormat = PixelFormat.RGB_ETC1;
+ transcoderFormat = BasisFormat.cTFETC1_RGB;
+ } else if (supportedTargetFormats.s3tc) {
+ internalFormat = hasAlpha ? PixelFormat.RGBA_DXT5 : PixelFormat.RGB_DXT1;
+ transcoderFormat = hasAlpha
+ ? BasisFormat.cTFBC3_RGBA
+ : BasisFormat.cTFBC1_RGB;
+ } else if (supportedTargetFormats.pvrtc) {
+ internalFormat = hasAlpha
+ ? PixelFormat.RGBA_PVRTC_4BPPV1
+ : PixelFormat.RGB_PVRTC_4BPPV1;
+ transcoderFormat = hasAlpha
+ ? BasisFormat.cTFPVRTC1_4_RGBA
+ : BasisFormat.cTFPVRTC1_4_RGB;
+ } else if (supportedTargetFormats.astc) {
+ internalFormat = PixelFormat.RGBA_ASTC;
+ transcoderFormat = BasisFormat.cTFASTC_4x4_RGBA;
+ } else if (supportedTargetFormats.bc7) {
+ internalFormat = PixelFormat.RGBA_BC7;
+ transcoderFormat = BasisFormat.cTFBC7_RGBA;
+ } else {
+ throw new RuntimeError(
+ "No transcoding format target available for ETC1S compressed ktx2."
+ );
+ }
+ } else if (dfd.colorModel === colorModelUASTC) {
+ if (supportedTargetFormats.astc) {
+ internalFormat = PixelFormat.RGBA_ASTC;
+ transcoderFormat = BasisFormat.cTFASTC_4x4_RGBA;
+ } else if (supportedTargetFormats.bc7) {
+ internalFormat = PixelFormat.RGBA_BC7;
+ transcoderFormat = BasisFormat.cTFBC7_RGBA;
+ } else if (supportedTargetFormats.s3tc) {
+ internalFormat = hasAlpha ? PixelFormat.RGBA_DXT5 : PixelFormat.RGB_DXT1;
+ transcoderFormat = hasAlpha
+ ? BasisFormat.cTFBC3_RGBA
+ : BasisFormat.cTFBC1_RGB;
+ } else if (supportedTargetFormats.etc) {
+ internalFormat = hasAlpha
+ ? PixelFormat.RGBA8_ETC2_EAC
+ : PixelFormat.RGB8_ETC2;
+ transcoderFormat = hasAlpha
+ ? BasisFormat.cTFETC2_RGBA
+ : BasisFormat.cTFETC1_RGB;
+ } else if (supportedTargetFormats.etc1 && !hasAlpha) {
+ internalFormat = PixelFormat.RGB_ETC1;
+ transcoderFormat = BasisFormat.cTFETC1_RGB;
+ } else if (supportedTargetFormats.pvrtc) {
+ internalFormat = hasAlpha
+ ? PixelFormat.RGBA_PVRTC_4BPPV1
+ : PixelFormat.RGB_PVRTC_4BPPV1;
+ transcoderFormat = hasAlpha
+ ? BasisFormat.cTFPVRTC1_4_RGBA
+ : BasisFormat.cTFPVRTC1_4_RGB;
+ } else {
+ throw new RuntimeError(
+ "No transcoding format target available for UASTC compressed ktx2."
+ );
+ }
+ }
+
+ if (!ktx2File.startTranscoding()) {
+ ktx2File.close();
+ ktx2File.delete();
+ throw new RuntimeError("startTranscoding() failed");
+ }
+
+ for (var i = 0; i < header.levels.length; ++i) {
+ var level = {};
+ result[i] = level;
+ width = header.pixelWidth >> i;
+ height = header.pixelHeight >> i;
+
+ // Since supercompressed cubemaps are unsupported, this function
+ // does not iterate over KTX2 faces and assumes faceCount = 1.
+
+ var dstSize = ktx2File.getImageTranscodedSizeInBytes(
+ i, // level index
+ 0, // layer index
+ 0, // face index
+ transcoderFormat.value
+ );
+ var dst = new Uint8Array(dstSize);
+
+ var transcoded = ktx2File.transcodeImage(
+ dst,
+ i, // level index
+ 0, // layer index
+ 0, // face index
+ transcoderFormat.value,
+ 0, // get_alpha_for_opaque_formats
+ -1, // channel0
+ -1 // channel1
+ );
+
+ if (!defined(transcoded)) {
+ throw new RuntimeError("transcodeImage() failed.");
+ }
+
+ transferableObjects.push(dst.buffer);
+
+ level[faceOrder[0]] = {
+ internalFormat: internalFormat,
+ width: width,
+ height: height,
+ levelBuffer: dst,
+ };
+ }
+
+ ktx2File.close();
+ ktx2File.delete();
+ return result;
+}
+
+export default parseKTX2;
diff --git a/Source/Renderer/Context.js b/Source/Renderer/Context.js
index cc8d5c326ef4..8f427707c232 100644
--- a/Source/Renderer/Context.js
+++ b/Source/Renderer/Context.js
@@ -9,6 +9,7 @@ import destroyObject from "../Core/destroyObject.js";
import DeveloperError from "../Core/DeveloperError.js";
import Geometry from "../Core/Geometry.js";
import GeometryAttribute from "../Core/GeometryAttribute.js";
+import loadKTX2 from "../Core/loadKTX2.js";
import Matrix4 from "../Core/Matrix4.js";
import PixelFormat from "../Core/PixelFormat.js";
import PrimitiveType from "../Core/PrimitiveType.js";
@@ -314,7 +315,21 @@ function Context(canvas, options) {
"WEBGL_compressed_texture_pvrtc",
"WEBKIT_WEBGL_compressed_texture_pvrtc",
]);
+ this._astc = !!getExtension(gl, ["WEBGL_compressed_texture_astc"]);
+ this._etc = !!getExtension(gl, ["WEBG_compressed_texture_etc"]);
this._etc1 = !!getExtension(gl, ["WEBGL_compressed_texture_etc1"]);
+ this._bc7 = !!getExtension(gl, ["EXT_texture_compression_bptc"]);
+
+ // It is necessary to pass supported formats to loadKTX2
+ // because imagery layers don't have access to the context.
+ loadKTX2.setKTX2SupportedFormats(
+ this._s3tc,
+ this._pvrtc,
+ this._astc,
+ this._etc,
+ this._etc1,
+ this._bc7
+ );
var textureFilterAnisotropic = options.allowTextureFilterAnisotropic
? getExtension(gl, [
@@ -665,7 +680,7 @@ Object.defineProperties(Context.prototype, {
* access to floating point textures that, for example, can be attached to framebuffers for high dynamic range.
* @memberof Context.prototype
* @type {Boolean}
- * @see {@link https://www.khronos.org/registry/webgl/extensions/OES_texture_float/}
+ * @see {@link https://www.khronos.org/registry/webgl/extensions/OES_texture_half_float/}
*/
halfFloatingPointTexture: {
get: function () {
@@ -716,7 +731,7 @@ Object.defineProperties(Context.prototype, {
},
/**
- * true
if WEBGL_texture_compression_s3tc is supported. This extension provides
+ * true
if WEBGL_compressed_texture_s3tc is supported. This extension provides
* access to DXT compressed textures.
* @memberof Context.prototype
* @type {Boolean}
@@ -729,7 +744,7 @@ Object.defineProperties(Context.prototype, {
},
/**
- * true
if WEBGL_texture_compression_pvrtc is supported. This extension provides
+ * true
if WEBGL_compressed_texture_pvrtc is supported. This extension provides
* access to PVR compressed textures.
* @memberof Context.prototype
* @type {Boolean}
@@ -742,7 +757,33 @@ Object.defineProperties(Context.prototype, {
},
/**
- * true
if WEBGL_texture_compression_etc1 is supported. This extension provides
+ * true
if WEBGL_compressed_texture_astc is supported. This extension provides
+ * access to ASTC compressed textures.
+ * @memberof Context.prototype
+ * @type {Boolean}
+ * @see {@link https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_astc/}
+ */
+ astc: {
+ get: function () {
+ return this._astc;
+ },
+ },
+
+ /**
+ * true
if WEBGL_compressed_texture_etc is supported. This extension provides
+ * access to ETC compressed textures.
+ * @memberof Context.prototype
+ * @type {Boolean}
+ * @see {@link https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc/}
+ */
+ etc: {
+ get: function () {
+ return this._etc;
+ },
+ },
+
+ /**
+ * true
if WEBGL_compressed_texture_etc1 is supported. This extension provides
* access to ETC1 compressed textures.
* @memberof Context.prototype
* @type {Boolean}
@@ -754,6 +795,37 @@ Object.defineProperties(Context.prototype, {
},
},
+ /**
+ * true
if EXT_texture_compression_bptc is supported. This extension provides
+ * access to BC7 compressed textures.
+ * @memberof Context.prototype
+ * @type {Boolean}
+ * @see {@link https://www.khronos.org/registry/webgl/extensions/EXT_texture_compression_bptc/}
+ */
+ bc7: {
+ get: function () {
+ return this._bc7;
+ },
+ },
+
+ /**
+ * true
if S3TC, PVRTC, ASTC, ETC, ETC1, or BC7 compression is supported.
+ * @memberof Context.prototype
+ * @type {Boolean}
+ */
+ supportsBasis: {
+ get: function () {
+ return (
+ this._s3tc ||
+ this._pvrtc ||
+ this._astc ||
+ this._etc ||
+ this._etc1 ||
+ this._bc7
+ );
+ },
+ },
+
/**
* true
if the OES_vertex_array_object extension is supported. This
* extension can improve performance by reducing the overhead of switching vertex arrays.
diff --git a/Source/Renderer/Texture.js b/Source/Renderer/Texture.js
index 58894466acbc..3340e1b61b8c 100644
--- a/Source/Renderer/Texture.js
+++ b/Source/Renderer/Texture.js
@@ -143,15 +143,27 @@ function Texture(options) {
if (PixelFormat.isDXTFormat(internalFormat) && !context.s3tc) {
throw new DeveloperError(
- "When options.pixelFormat is S3TC compressed, this WebGL implementation must support the WEBGL_texture_compression_s3tc extension. Check context.s3tc."
+ "When options.pixelFormat is S3TC compressed, this WebGL implementation must support the WEBGL_compressed_texture_s3tc extension. Check context.s3tc."
);
} else if (PixelFormat.isPVRTCFormat(internalFormat) && !context.pvrtc) {
throw new DeveloperError(
- "When options.pixelFormat is PVRTC compressed, this WebGL implementation must support the WEBGL_texture_compression_pvrtc extension. Check context.pvrtc."
+ "When options.pixelFormat is PVRTC compressed, this WebGL implementation must support the WEBGL_compressed_texture_pvrtc extension. Check context.pvrtc."
+ );
+ } else if (PixelFormat.isASTCFormat(internalFormat) && !context.astc) {
+ throw new DeveloperError(
+ "When options.pixelFormat is ASTC compressed, this WebGL implementation must support the WEBGL_compressed_texture_astc extension. Check context.astc."
+ );
+ } else if (PixelFormat.isETC2Format(internalFormat) && !context.etc) {
+ throw new DeveloperError(
+ "When options.pixelFormat is ETC2 compressed, this WebGL implementation must support the WEBGL_compressed_texture_etc extension. Check context.etc."
);
} else if (PixelFormat.isETC1Format(internalFormat) && !context.etc1) {
throw new DeveloperError(
- "When options.pixelFormat is ETC1 compressed, this WebGL implementation must support the WEBGL_texture_compression_etc1 extension. Check context.etc1."
+ "When options.pixelFormat is ETC1 compressed, this WebGL implementation must support the WEBGL_compressed_texture_etc1 extension. Check context.etc1."
+ );
+ } else if (PixelFormat.isBC7Format(internalFormat) && !context.bc7) {
+ throw new DeveloperError(
+ "When options.pixelFormat is BC7 compressed, this WebGL implementation must support the EXT_texture_compression_bptc extension. Check context.bc7."
);
}
@@ -217,6 +229,7 @@ function Texture(options) {
// Source: typed array
var arrayBufferView = source.arrayBufferView;
+ var i, mipWidth, mipHeight;
if (isCompressed) {
gl.compressedTexImage2D(
textureTarget,
@@ -227,6 +240,29 @@ function Texture(options) {
0,
arrayBufferView
);
+ if (defined(source.mipLevels)) {
+ mipWidth = width;
+ mipHeight = height;
+ for (i = 0; i < source.mipLevels.length; ++i) {
+ mipWidth = Math.floor(mipWidth / 2) | 0;
+ if (mipWidth < 1) {
+ mipWidth = 1;
+ }
+ mipHeight = Math.floor(mipHeight / 2) | 0;
+ if (mipHeight < 1) {
+ mipHeight = 1;
+ }
+ gl.compressedTexImage2D(
+ textureTarget,
+ i + 1,
+ internalFormat,
+ mipWidth,
+ mipHeight,
+ 0,
+ source.mipLevels[i]
+ );
+ }
+ }
} else {
if (flipY) {
arrayBufferView = PixelFormat.flipY(
@@ -250,9 +286,9 @@ function Texture(options) {
);
if (defined(source.mipLevels)) {
- var mipWidth = width;
- var mipHeight = height;
- for (var i = 0; i < source.mipLevels.length; ++i) {
+ mipWidth = width;
+ mipHeight = height;
+ for (i = 0; i < source.mipLevels.length; ++i) {
mipWidth = Math.floor(mipWidth / 2) | 0;
if (mipWidth < 1) {
mipWidth = 1;
diff --git a/Source/Scene/BufferLoader.js b/Source/Scene/BufferLoader.js
index 63ee39af5b1d..613649c56fe7 100644
--- a/Source/Scene/BufferLoader.js
+++ b/Source/Scene/BufferLoader.js
@@ -108,8 +108,7 @@ BufferLoader.prototype.load = function () {
function loadExternalBuffer(bufferLoader) {
var resource = bufferLoader._resource;
bufferLoader._state = ResourceLoaderState.LOADING;
- resource
- .fetchArrayBuffer()
+ BufferLoader._fetchArrayBuffer(resource)
.then(function (arrayBuffer) {
if (bufferLoader.isDestroyed()) {
return;
@@ -128,6 +127,14 @@ function loadExternalBuffer(bufferLoader) {
});
}
+/**
+ * Exposed for testing
+ * @private
+ */
+BufferLoader._fetchArrayBuffer = function (resource) {
+ return resource.fetchArrayBuffer();
+};
+
/**
* Unloads the resource.
* @private
diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js
index 3ea01f7ead08..82dcb932e1d4 100644
--- a/Source/Scene/Cesium3DTileset.js
+++ b/Source/Scene/Cesium3DTileset.js
@@ -94,7 +94,7 @@ import TileOrientedBoundingBox from "./TileOrientedBoundingBox.js";
* @param {Cartesian3} [options.lightColor] The light color when shading models. When undefined
the scene's light color is used instead.
* @param {Number} [options.luminanceAtZenith=0.2] The sun's luminance at the zenith in kilo candela per meter squared to use for this model's procedural environment map.
* @param {Cartesian3[]} [options.sphericalHarmonicCoefficients] The third order spherical harmonic coefficients used for the diffuse color of image-based lighting.
- * @param {String} [options.specularEnvironmentMaps] A URL to a KTX file that contains a cube map of the specular lighting and the convoluted specular mipmaps.
+ * @param {String} [options.specularEnvironmentMaps] A URL to a KTX2 file that contains a cube map of the specular lighting and the convoluted specular mipmaps.
* @param {Boolean} [options.backFaceCulling=true] Whether to cull back-facing geometry. When true, back face culling is determined by the glTF material's doubleSided property; when false, back face culling is disabled.
* @param {Boolean} [options.showOutline=true] Whether to display the outline for models using the {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/CESIUM_primitive_outline|CESIUM_primitive_outline} extension. When true, outlines are displayed. When false, outlines are not displayed.
* @param {Boolean} [options.vectorClassificationOnly=false] Indicates that only the tileset's vector tiles should be used for classification.
diff --git a/Source/Scene/GltfImageLoader.js b/Source/Scene/GltfImageLoader.js
index 7fd4c70079f4..712975bd811e 100644
--- a/Source/Scene/GltfImageLoader.js
+++ b/Source/Scene/GltfImageLoader.js
@@ -1,12 +1,10 @@
import Check from "../Core/Check.js";
import defaultValue from "../Core/defaultValue.js";
import defined from "../Core/defined.js";
-import loadCRN from "../Core/loadCRN.js";
import loadImageFromTypedArray from "../Core/loadImageFromTypedArray.js";
-import loadKTX from "../Core/loadKTX.js";
+import loadKTX2 from "../Core/loadKTX2.js";
import RuntimeError from "../Core/RuntimeError.js";
import when from "../ThirdParty/when.js";
-import GltfLoaderUtil from "./GltfLoaderUtil.js";
import ResourceLoader from "./ResourceLoader.js";
import ResourceLoaderState from "./ResourceLoaderState.js";
@@ -26,7 +24,6 @@ import ResourceLoaderState from "./ResourceLoaderState.js";
* @param {Number} options.imageId The image ID.
* @param {Resource} options.gltfResource The {@link Resource} containing the glTF.
* @param {Resource} options.baseResource The {@link Resource} that paths in the glTF JSON are relative to.
- * @param {SupportedImageFormats} options.supportedImageFormats The supported image formats.
* @param {String} [options.cacheKey] The cache key of the resource.
*
* @private
@@ -38,7 +35,6 @@ export default function GltfImageLoader(options) {
var imageId = options.imageId;
var gltfResource = options.gltfResource;
var baseResource = options.baseResource;
- var supportedImageFormats = options.supportedImageFormats;
var cacheKey = options.cacheKey;
//>>includeStart('debug', pragmas.debug);
@@ -47,17 +43,11 @@ export default function GltfImageLoader(options) {
Check.typeOf.number("options.imageId", imageId);
Check.typeOf.object("options.gltfResource", gltfResource);
Check.typeOf.object("options.baseResource", baseResource);
- Check.typeOf.object("options.supportedImageFormats", supportedImageFormats);
//>>includeEnd('debug');
- var results = GltfLoaderUtil.getImageUriOrBufferView({
- gltf: gltf,
- imageId: imageId,
- supportedImageFormats: supportedImageFormats,
- });
-
- var bufferViewId = results.bufferViewId;
- var uri = results.uri;
+ var image = gltf.images[imageId];
+ var bufferViewId = image.bufferView;
+ var uri = image.uri;
this._resourceCache = resourceCache;
this._gltfResource = gltfResource;
@@ -68,6 +58,7 @@ export default function GltfImageLoader(options) {
this._cacheKey = cacheKey;
this._bufferViewLoader = undefined;
this._image = undefined;
+ this._mipLevels = undefined;
this._state = ResourceLoaderState.UNLOADED;
this._promise = when.defer();
}
@@ -120,6 +111,20 @@ Object.defineProperties(GltfImageLoader.prototype, {
return this._image;
},
},
+ /**
+ * The mip levels. Only defined for KTX2 files containing mip levels.
+ *
+ * @memberof GltfImageLoader.prototype
+ *
+ * @type {Uint8Array[]}
+ * @readonly
+ * @private
+ */
+ mipLevels: {
+ get: function () {
+ return this._mipLevels;
+ },
+ },
});
/**
@@ -134,6 +139,23 @@ GltfImageLoader.prototype.load = function () {
}
};
+function getImageAndMipLevels(image) {
+ // Images transcoded from KTX2 can contain multiple mip levels:
+ // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_basisu
+ var mipLevels;
+ if (Array.isArray(image)) {
+ // highest detail mip should be level 0
+ mipLevels = image.slice(1, image.length).map(function (mipLevel) {
+ return mipLevel.bufferView;
+ });
+ image = image[0];
+ }
+ return {
+ image: image,
+ mipLevels: mipLevels,
+ };
+}
+
function loadFromBufferView(imageLoader) {
var resourceCache = imageLoader._resourceCache;
var bufferViewLoader = resourceCache.loadBufferView({
@@ -158,10 +180,13 @@ function loadFromBufferView(imageLoader) {
return;
}
+ var imageAndMipLevels = getImageAndMipLevels(image);
+
// Unload everything except the image
imageLoader.unload();
- imageLoader._image = image;
+ imageLoader._image = imageAndMipLevels.image;
+ imageLoader._mipLevels = imageAndMipLevels.mipLevels;
imageLoader._state = ResourceLoaderState.READY;
imageLoader._promise.resolve(imageLoader);
});
@@ -187,10 +212,13 @@ function loadFromUri(imageLoader) {
return;
}
+ var imageAndMipLevels = getImageAndMipLevels(image);
+
// Unload everything except the image
imageLoader.unload();
- imageLoader._image = image;
+ imageLoader._image = imageAndMipLevels.image;
+ imageLoader._mipLevels = imageAndMipLevels.mipLevels;
imageLoader._state = ResourceLoaderState.READY;
imageLoader._promise.resolve(imageLoader);
})
@@ -221,13 +249,7 @@ function getMimeTypeFromTypedArray(typedArray) {
return "image/png";
} else if (header[0] === 0xab && header[1] === 0x4b) {
// See http://github.khronos.org/KTX-Specification/#_identifier
- return "image/ktx";
- } else if (header[0] === 0x48 && header[1] === 0x78) {
- // See https://github.com/BinomialLLC/crunch/blob/671a0648c8a440b4397f1d96ea5cf5700f830417/inc/crn_decomp.h#L268
- return "image/crn";
- } else if (header[0] === 0x73 && header[1] === 0x42) {
- // See https://github.com/BinomialLLC/basis_universal/blob/ed135f03a05de315dd7ec7c1b8ef0589099b3e52/spec/basis_spec.txt#L125
- return "image/basis";
+ return "image/ktx2";
} else if (
// See https://developers.google.com/speed/webp/docs/riff_container#webp_file_header
webpHeaderRIFFChars[0] === 0x52 &&
@@ -247,12 +269,15 @@ function getMimeTypeFromTypedArray(typedArray) {
function loadImageFromBufferTypedArray(typedArray) {
var mimeType = getMimeTypeFromTypedArray(typedArray);
- if (mimeType === "image/ktx") {
- // Resolves to a CompressedTextureBuffer
- return loadKTX(typedArray);
- } else if (mimeType === "image/crn") {
+ if (mimeType === "image/ktx2") {
+ // Need to make a copy of the embedded KTX2 buffer otherwise the underlying
+ // ArrayBuffer may be accessed on both the worker and the main thread and
+ // throw an error like "Cannot perform Construct on a detached ArrayBuffer".
+ // Look into SharedArrayBuffer at some point to get around this.
+ var ktxBuffer = new Uint8Array(typedArray);
+
// Resolves to a CompressedTextureBuffer
- return loadCRN(typedArray);
+ return loadKTX2(ktxBuffer);
}
// Resolves to an Image or ImageBitmap
return GltfImageLoader._loadImageFromTypedArray({
@@ -263,17 +288,13 @@ function loadImageFromBufferTypedArray(typedArray) {
});
}
-var ktxRegex = /(^data:image\/ktx)|(\.ktx$)/i;
-var crnRegex = /(^data:image\/crn)|(\.crn$)/i;
+var ktx2Regex = /(^data:image\/ktx2)|(\.ktx2$)/i;
function loadImageFromUri(resource) {
var uri = resource.url;
- if (ktxRegex.test(uri)) {
- // Resolves to a CompressedTextureBuffer
- return loadKTX(resource);
- } else if (crnRegex.test(uri)) {
+ if (ktx2Regex.test(uri)) {
// Resolves to a CompressedTextureBuffer
- return loadCRN(resource);
+ return loadKTX2(resource);
}
// Resolves to an ImageBitmap or Image
return resource.fetchImage({
@@ -294,8 +315,9 @@ GltfImageLoader.prototype.unload = function () {
this._bufferViewLoader = undefined;
this._uri = undefined; // Free in case the uri is a data uri
this._image = undefined;
+ this._mipLevels = undefined;
this._gltf = undefined;
};
-//Exposed for testing
+// Exposed for testing
GltfImageLoader._loadImageFromTypedArray = loadImageFromTypedArray;
diff --git a/Source/Scene/GltfLoader.js b/Source/Scene/GltfLoader.js
index a4b17d7041dd..95939ab7cdce 100644
--- a/Source/Scene/GltfLoader.js
+++ b/Source/Scene/GltfLoader.js
@@ -263,9 +263,7 @@ GltfLoader.prototype.process = function (frameState) {
var supportedImageFormats = new SupportedImageFormats({
webp: FeatureDetection.supportsWebP(),
- s3tc: frameState.context.s3tc,
- pvrtc: frameState.context.pvrtc,
- etc1: frameState.context.etc1,
+ basis: frameState.context.supportsBasis,
});
var gltf = this._gltfJsonLoader.gltf;
diff --git a/Source/Scene/GltfLoaderUtil.js b/Source/Scene/GltfLoaderUtil.js
index c6f5d35a1f4e..7f6fabf5c0e3 100644
--- a/Source/Scene/GltfLoaderUtil.js
+++ b/Source/Scene/GltfLoaderUtil.js
@@ -18,75 +18,6 @@ import ModelComponents from "./ModelComponents.js";
*/
var GltfLoaderUtil = {};
-/**
- * Get the uri or buffer view for an image.
- *
- * @param {Object} options Object with the following properties:
- * @param {Object} options.gltf The glTF JSON.
- * @param {Number} options.imageId The image ID.
- * @param {SupportedImageFormats} options.supportedImageFormats The supported image formats.
- *
- * @returns {Object} An object containing a uri
and bufferView
property.
- * @private
- */
-GltfLoaderUtil.getImageUriOrBufferView = function (options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- var gltf = options.gltf;
- var imageId = options.imageId;
- var supportedImageFormats = options.supportedImageFormats;
-
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options.gltf", gltf);
- Check.typeOf.number("options.imageId", imageId);
- Check.typeOf.object("options.supportedImageFormats", supportedImageFormats);
- //>>includeEnd('debug');
-
- var image = gltf.images[imageId];
- var extras = image.extras;
-
- var bufferViewId = image.bufferView;
- var uri = image.uri;
-
- // First check for a compressed texture
- if (defined(extras) && defined(extras.compressedImage3DTiles)) {
- var crunch = extras.compressedImage3DTiles.crunch;
- var s3tc = extras.compressedImage3DTiles.s3tc;
- var pvrtc = extras.compressedImage3DTiles.pvrtc1;
- var etc1 = extras.compressedImage3DTiles.etc1;
-
- if (supportedImageFormats.s3tc && defined(crunch)) {
- if (defined(crunch.bufferView)) {
- bufferViewId = crunch.bufferView;
- } else {
- uri = crunch.uri;
- }
- } else if (supportedImageFormats.s3tc && defined(s3tc)) {
- if (defined(s3tc.bufferView)) {
- bufferViewId = s3tc.bufferView;
- } else {
- uri = s3tc.uri;
- }
- } else if (supportedImageFormats.pvrtc && defined(pvrtc)) {
- if (defined(pvrtc.bufferView)) {
- bufferViewId = pvrtc.bufferView;
- } else {
- uri = pvrtc.uri;
- }
- } else if (supportedImageFormats.etc1 && defined(etc1)) {
- if (defined(etc1.bufferView)) {
- bufferViewId = etc1.bufferView;
- } else {
- uri = etc1.uri;
- }
- }
- }
-
- return {
- bufferViewId: bufferViewId,
- uri: uri,
- };
-};
-
/**
* Get the image ID referenced by a texture.
* @@ -119,6 +50,11 @@ GltfLoaderUtil.getImageIdFromTexture = function (options) { if (defined(extensions)) { if (supportedImageFormats.webp && defined(extensions.EXT_texture_webp)) { return extensions.EXT_texture_webp.source; + } else if ( + supportedImageFormats.basis && + defined(extensions.KHR_texture_basisu) + ) { + return extensions.KHR_texture_basisu.source; } } return texture.source; @@ -130,6 +66,7 @@ GltfLoaderUtil.getImageIdFromTexture = function (options) { * @param {Object} options Object with the following properties: * @param {Object} options.gltf The glTF JSON. * @param {Object} options.textureInfo The texture info object. + * @param {Boolean} [options.compressedTextureNoMipmap=false] True when the texture is compressed and does not have an embedded mipmap. * * @returns {Sampler} The sampler. * @private @@ -138,6 +75,10 @@ GltfLoaderUtil.createSampler = function (options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); var gltf = options.gltf; var textureInfo = options.textureInfo; + var compressedTextureNoMipmap = defaultValue( + options.compressedTextureNoMipmap, + false + ); //>>includeStart('debug', pragmas.debug); Check.typeOf.object("options.gltf", gltf); @@ -169,7 +110,7 @@ GltfLoaderUtil.createSampler = function (options) { } if ( - usesTextureTransform && + (compressedTextureNoMipmap || usesTextureTransform) && minFilter !== TextureMinificationFilter.LINEAR && minFilter !== TextureMinificationFilter.NEAREST ) { diff --git a/Source/Scene/GltfTextureLoader.js b/Source/Scene/GltfTextureLoader.js index 6a6594729069..8017767a9ca0 100644 --- a/Source/Scene/GltfTextureLoader.js +++ b/Source/Scene/GltfTextureLoader.js @@ -2,6 +2,7 @@ import Check from "../Core/Check.js"; import CesiumMath from "../Core/Math.js"; import defaultValue from "../Core/defaultValue.js"; import defined from "../Core/defined.js"; +import PixelFormat from "../Core/PixelFormat.js"; import Texture from "../Renderer/Texture.js"; import TextureMinificationFilter from "../Renderer/TextureMinificationFilter.js"; import TextureWrap from "../Renderer/TextureWrap.js"; @@ -69,11 +70,11 @@ export default function GltfTextureLoader(options) { this._imageId = imageId; this._gltfResource = gltfResource; this._baseResource = baseResource; - this._supportedImageFormats = supportedImageFormats; this._cacheKey = cacheKey; this._asynchronous = asynchronous; this._imageLoader = undefined; this._image = undefined; + this._mipLevels = undefined; this._texture = undefined; this._state = ResourceLoaderState.UNLOADED; this._promise = when.defer(); @@ -140,7 +141,6 @@ GltfTextureLoader.prototype.load = function () { imageId: this._imageId, gltfResource: this._gltfResource, baseResource: this._baseResource, - supportedImageFormats: this._supportedImageFormats, }); this._imageLoader = imageLoader; @@ -155,6 +155,7 @@ GltfTextureLoader.prototype.load = function () { } // Now wait for process() to run to finish loading that._image = imageLoader.image; + that._mipLevels = imageLoader.mipLevels; that._state = ResourceLoaderState.PROCESSING; }) .otherwise(function (error) { @@ -176,10 +177,17 @@ function CreateTextureJob() { this.texture = undefined; } -CreateTextureJob.prototype.set = function (gltf, textureInfo, image, context) { +CreateTextureJob.prototype.set = function ( + gltf, + textureInfo, + image, + mipLevels, + context +) { this.gltf = gltf; this.textureInfo = textureInfo; this.image = image; + this.mipLevels = mipLevels; this.context = context; }; @@ -188,6 +196,7 @@ CreateTextureJob.prototype.execute = function () { this.gltf, this.textureInfo, this.image, + this.mipLevels, this.context ); }; @@ -211,19 +220,25 @@ function resizeImageToNextPowerOfTwo(image) { return canvas; } -function createTexture(gltf, textureInfo, image, context) { +function createTexture(gltf, textureInfo, image, mipLevels, context) { + // internalFormat is only defined for CompressedTextureBuffer + var internalFormat = image.internalFormat; + + var compressedTextureNoMipmap = false; + if (PixelFormat.isCompressedFormat(internalFormat) && !defined(mipLevels)) { + compressedTextureNoMipmap = true; + } + var sampler = GltfLoaderUtil.createSampler({ gltf: gltf, textureInfo: textureInfo, + compressedTextureNoMipmap: compressedTextureNoMipmap, }); var minFilter = sampler.minificationFilter; var wrapS = sampler.wrapS; var wrapT = sampler.wrapT; - // internalFormat is only defined for CompressedTextureBuffer - var internalFormat = image.internalFormat; - var samplerRequiresMipmap = minFilter === TextureMinificationFilter.NEAREST_MIPMAP_NEAREST || minFilter === TextureMinificationFilter.NEAREST_MIPMAP_LINEAR || @@ -235,7 +250,7 @@ function createTexture(gltf, textureInfo, image, context) { // WebGL. Also note from the KHR_texture_basisu spec: // // When a texture refers to a sampler with mipmap minification or when the - // sampler is undefined, the KTX image SHOULD contain a full mip pyramid. + // sampler is undefined, the KTX2 image SHOULD contain a full mip pyramid. // var generateMipmap = !defined(internalFormat) && samplerRequiresMipmap; @@ -255,10 +270,22 @@ function createTexture(gltf, textureInfo, image, context) { var texture; if (defined(internalFormat)) { + if ( + !context.webgl2 && + PixelFormat.isCompressedFormat(internalFormat) && + nonPowerOfTwo && + requiresPowerOfTwo + ) { + console.warn( + "Compressed texture uses REPEAT or MIRRORED_REPEAT texture wrap mode and dimensions are not powers of two. The texture may be rendered incorrectly." + ); + } + texture = Texture.create({ context: context, source: { arrayBufferView: image.bufferView, // Only defined for CompressedTextureBuffer + mipLevels: mipLevels, }, width: image.width, height: image.height, @@ -316,6 +343,7 @@ GltfTextureLoader.prototype.process = function (frameState) { this._gltf, this._textureInfo, this._image, + this._mipLevels, frameState.context ); var jobScheduler = frameState.jobScheduler; @@ -329,6 +357,7 @@ GltfTextureLoader.prototype.process = function (frameState) { this._gltf, this._textureInfo, this._image, + this._mipLevels, frameState.context ); } @@ -356,6 +385,7 @@ GltfTextureLoader.prototype.unload = function () { this._imageLoader = undefined; this._image = undefined; + this._mipLevels = undefined; this._texture = undefined; this._gltf = undefined; }; diff --git a/Source/Scene/ImageryProvider.js b/Source/Scene/ImageryProvider.js index 297ce3044137..35dfd0abe51b 100644 --- a/Source/Scene/ImageryProvider.js +++ b/Source/Scene/ImageryProvider.js @@ -1,8 +1,7 @@ import Check from "../Core/Check.js"; import defined from "../Core/defined.js"; import DeveloperError from "../Core/DeveloperError.js"; -import loadCRN from "../Core/loadCRN.js"; -import loadKTX from "../Core/loadKTX.js"; +import loadKTX2 from "../Core/loadKTX2.js"; import Resource from "../Core/Resource.js"; /** @@ -337,8 +336,7 @@ ImageryProvider.prototype.pickFeatures = function ( DeveloperError.throwInstantiationError(); }; -var ktxRegex = /\.ktx$/i; -var crnRegex = /\.crn$/i; +var ktx2Regex = /\.ktx2$/i; /** * Loads an image from a given URL. If the server referenced by the URL already has @@ -359,10 +357,8 @@ ImageryProvider.loadImage = function (imageryProvider, url) { var resource = Resource.createIfNeeded(url); - if (ktxRegex.test(resource.url)) { - return loadKTX(resource); - } else if (crnRegex.test(resource.url)) { - return loadCRN(resource); + if (ktx2Regex.test(resource.url)) { + return loadKTX2(resource); } else if ( defined(imageryProvider) && defined(imageryProvider.tileDiscardPolicy) diff --git a/Source/Scene/Material.js b/Source/Scene/Material.js index 8b4212fa39d1..bb681110d593 100644 --- a/Source/Scene/Material.js +++ b/Source/Scene/Material.js @@ -7,8 +7,7 @@ import defaultValue from "../Core/defaultValue.js"; import defined from "../Core/defined.js"; import destroyObject from "../Core/destroyObject.js"; import DeveloperError from "../Core/DeveloperError.js"; -import loadCRN from "../Core/loadCRN.js"; -import loadKTX from "../Core/loadKTX.js"; +import loadKTX2 from "../Core/loadKTX2.js"; import Matrix2 from "../Core/Matrix2.js"; import Matrix3 from "../Core/Matrix3.js"; import Matrix4 from "../Core/Matrix4.js"; @@ -434,6 +433,17 @@ Material.prototype.update = function (context) { uniformId = loadedImage.id; var image = loadedImage.image; + // Images transcoded from KTX2 can contain multiple mip levels: + // https://github.khronos.org/KTX-Specification/#_mip_level_array + var mipLevels; + if (Array.isArray(image)) { + // highest detail mip should be level 0 + mipLevels = image.slice(1, image.length).map(function (mipLevel) { + return mipLevel.bufferView; + }); + image = image[0]; + } + var sampler = new Sampler({ minificationFilter: this._minificationFilter, magnificationFilter: this._magnificationFilter, @@ -448,6 +458,7 @@ Material.prototype.update = function (context) { height: image.height, source: { arrayBufferView: image.bufferView, + mipLevels: mipLevels, }, sampler: sampler, }); @@ -776,8 +787,7 @@ var matrixMap = { mat4: Matrix4, }; -var ktxRegex = /\.ktx$/i; -var crnRegex = /\.crn$/i; +var ktx2Regex = /\.ktx2$/i; function createTexture2DUpdateFunction(uniformId) { var oldUniformValue; @@ -879,13 +889,12 @@ function createTexture2DUpdateFunction(uniformId) { : Resource.createIfNeeded(uniformValue); var promise; - if (ktxRegex.test(resource.url)) { - promise = loadKTX(resource); - } else if (crnRegex.test(resource.url)) { - promise = loadCRN(resource); + if (ktx2Regex.test(resource.url)) { + promise = loadKTX2(resource.url); } else { promise = resource.fetchImage(); } + when(promise, function (image) { material._loadedImages.push({ id: uniformId, diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index 098b121cf750..30cfb090481c 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -20,9 +20,8 @@ import getJsonFromTypedArray from "../Core/getJsonFromTypedArray.js"; import getMagic from "../Core/getMagic.js"; import getStringFromTypedArray from "../Core/getStringFromTypedArray.js"; import IndexDatatype from "../Core/IndexDatatype.js"; -import loadCRN from "../Core/loadCRN.js"; import loadImageFromTypedArray from "../Core/loadImageFromTypedArray.js"; -import loadKTX from "../Core/loadKTX.js"; +import loadKTX2 from "../Core/loadKTX2.js"; import CesiumMath from "../Core/Math.js"; import Matrix3 from "../Core/Matrix3.js"; import Matrix4 from "../Core/Matrix4.js"; @@ -175,10 +174,17 @@ var uriToGuid = {}; * {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_techniques_webgl/README.md|KHR_techniques_webgl} *
+ * Note: for models with compressed textures using the KHR_texture_basisu extension, we recommend power of 2 textures in both dimensions + * for maximum compatibility. This is because some samplers require power of 2 textures ({@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL|Using textures in WebGL}) + * and KHR_texture_basisu requires multiple of 4 dimensions ({@link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_texture_basisu/README.md#additional-requirements|KHR_texture_basisu additional requirements}). + *
+ *
* For high-precision rendering, Cesium supports the {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/1.0/Vendor/CESIUM_RTC/README.md|CESIUM_RTC} extension, which introduces the
* CESIUM_RTC_MODELVIEW parameter semantic that says the node is in WGS84 coordinates translated
* relative to a local origin.
@@ -217,7 +223,7 @@ var uriToGuid = {};
* @param {Cartesian3} [options.lightColor] The light color when shading the model. When undefined
the scene's light color is used instead.
* @param {Number} [options.luminanceAtZenith=0.2] The sun's luminance at the zenith in kilo candela per meter squared to use for this model's procedural environment map.
* @param {Cartesian3[]} [options.sphericalHarmonicCoefficients] The third order spherical harmonic coefficients used for the diffuse color of image-based lighting.
- * @param {String} [options.specularEnvironmentMaps] A URL to a KTX file that contains a cube map of the specular lighting and the convoluted specular mipmaps.
+ * @param {String} [options.specularEnvironmentMaps] A URL to a KTX2 file that contains a cube map of the specular lighting and the convoluted specular mipmaps.
* @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas.
* @param {Boolean} [options.backFaceCulling=true] Whether to cull back-facing geometry. When true, back face culling is determined by the material's doubleSided property; when false, back face culling is disabled. Back faces are not culled if {@link Model#color} is translucent or {@link Model#silhouetteSize} is greater than 0.0.
* @param {Boolean} [options.showOutline=true] Whether to display the outline for models using the {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/CESIUM_primitive_outline|CESIUM_primitive_outline} extension. When true, outlines are displayed. When false, outlines are not displayed.
@@ -1282,7 +1288,7 @@ Object.defineProperties(Model.prototype, {
},
/**
- * A URL to a KTX file that contains a cube map of the specular lighting and the convoluted specular mipmaps.
+ * A URL to a KTX2 file that contains a cube map of the specular lighting and the convoluted specular mipmaps.
*
* @memberof Model.prototype
* @demo {@link https://sandcastle.cesium.com/index.html?src=Image-Based Lighting.html|Sandcastle Image Based Lighting Demo}
@@ -1378,6 +1384,8 @@ function containsGltfMagic(uint8Array) {
* {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_techniques_webgl/README.md|KHR_techniques_webgl}
*
undefined
the scene's light color is used instead.
* @param {Number} [options.luminanceAtZenith=0.2] The sun's luminance at the zenith in kilo candela per meter squared to use for this model's procedural environment map.
* @param {Cartesian3[]} [options.sphericalHarmonicCoefficients] The third order spherical harmonic coefficients used for the diffuse color of image-based lighting.
- * @param {String} [options.specularEnvironmentMaps] A URL to a KTX file that contains a cube map of the specular lighting and the convoluted specular mipmaps.
+ * @param {String} [options.specularEnvironmentMaps] A URL to a KTX2 file that contains a cube map of the specular lighting and the convoluted specular mipmaps.
* @param {Boolean} [options.backFaceCulling=true] Whether to cull back-facing geometry. When true, back face culling is determined by the glTF material's doubleSided property; when false, back face culling is disabled.
* @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Draws the bounding sphere for the collection.
* @param {Boolean} [options.debugWireframe=false] For debugging only. Draws the instances in wireframe.
diff --git a/Source/Scene/ModelUtility.js b/Source/Scene/ModelUtility.js
index e2948c84b26d..6822468d584a 100644
--- a/Source/Scene/ModelUtility.js
+++ b/Source/Scene/ModelUtility.js
@@ -564,6 +564,7 @@ ModelUtility.supportedExtensions = {
EXT_texture_webp: true,
KHR_blend: true,
KHR_binary_glTF: true,
+ KHR_texture_basisu: true,
KHR_draco_mesh_compression: true,
KHR_materials_common: true,
KHR_techniques_webgl: true,
diff --git a/Source/Scene/OctahedralProjectedCubeMap.js b/Source/Scene/OctahedralProjectedCubeMap.js
index 1de61027cc73..fc721c3ab71c 100644
--- a/Source/Scene/OctahedralProjectedCubeMap.js
+++ b/Source/Scene/OctahedralProjectedCubeMap.js
@@ -3,7 +3,7 @@ import ComponentDatatype from "../Core/ComponentDatatype.js";
import defined from "../Core/defined.js";
import destroyObject from "../Core/destroyObject.js";
import IndexDatatype from "../Core/IndexDatatype.js";
-import loadKTX from "../Core/loadKTX.js";
+import loadKTX2 from "../Core/loadKTX2.js";
import PixelFormat from "../Core/PixelFormat.js";
import Buffer from "../Renderer/Buffer.js";
import BufferUsage from "../Renderer/BufferUsage.js";
@@ -11,6 +11,7 @@ import ComputeCommand from "../Renderer/ComputeCommand.js";
import CubeMap from "../Renderer/CubeMap.js";
import PixelDatatype from "../Renderer/PixelDatatype.js";
import ShaderProgram from "../Renderer/ShaderProgram.js";
+import ShaderSource from "../Renderer/ShaderSource.js";
import Texture from "../Renderer/Texture.js";
import VertexArray from "../Renderer/VertexArray.js";
import OctahedralProjectionAtlasFS from "../Shaders/OctahedralProjectionAtlasFS.js";
@@ -47,7 +48,7 @@ function OctahedralProjectedCubeMap(url) {
Object.defineProperties(OctahedralProjectedCubeMap.prototype, {
/**
- * The url to the KTX file containing the specular environment map and convoluted mipmaps.
+ * The url to the KTX2 file containing the specular environment map and convoluted mipmaps.
* @memberof OctahedralProjectedCubeMap.prototype
* @type {String}
* @readonly
@@ -290,7 +291,7 @@ OctahedralProjectedCubeMap.prototype.update = function (frameState) {
var cubeMapBuffers = this._cubeMapBuffers;
if (!defined(cubeMapBuffers) && !this._loading) {
var that = this;
- loadKTX(this._url)
+ loadKTX2(this._url)
.then(function (buffers) {
that._cubeMapBuffers = buffers;
that._loading = false;
@@ -302,11 +303,28 @@ OctahedralProjectedCubeMap.prototype.update = function (frameState) {
return;
}
+ var defines = [];
+ // Datatype is defined if it is a normalized type (i.e. ..._UNORM, ..._SFLOAT)
+ var pixelDatatype = cubeMapBuffers[0].positiveX.pixelDatatype;
+ if (!defined(pixelDatatype)) {
+ pixelDatatype = context.halfFloatingPointTexture
+ ? PixelDatatype.HALF_FLOAT
+ : PixelDatatype.FLOAT;
+ } else {
+ defines.push("RGBA_NORMALIZED");
+ }
+ var pixelFormat = PixelFormat.RGBA;
+
+ var fs = new ShaderSource({
+ defines: defines,
+ sources: [OctahedralProjectionFS],
+ });
+
this._va = createVertexArray(context);
this._sp = ShaderProgram.fromCache({
context: context,
vertexShaderSource: OctahedralProjectionVS,
- fragmentShaderSource: OctahedralProjectionFS,
+ fragmentShaderSource: fs,
attributeLocations: {
position: 0,
cubeMapCoordinates: 1,
@@ -325,11 +343,6 @@ OctahedralProjectedCubeMap.prototype.update = function (frameState) {
},
};
- var pixelDatatype = context.halfFloatingPointTexture
- ? PixelDatatype.HALF_FLOAT
- : PixelDatatype.FLOAT;
- var pixelFormat = PixelFormat.RGBA;
-
// First we project each cubemap onto a flat octahedron, and write that to a texture.
for (var i = 0; i < length; ++i) {
// Swap +Y/-Y faces since the octahedral projection expects this order.
@@ -340,6 +353,7 @@ OctahedralProjectedCubeMap.prototype.update = function (frameState) {
var cubeMap = (cubeMaps[i] = new CubeMap({
context: context,
source: cubeMapBuffers[i],
+ pixelDatatype: pixelDatatype,
}));
var size = cubeMaps[i].width * 2;
diff --git a/Source/Scene/ResourceCache.js b/Source/Scene/ResourceCache.js
index e5301bf6f4ad..848f3938ee76 100644
--- a/Source/Scene/ResourceCache.js
+++ b/Source/Scene/ResourceCache.js
@@ -587,7 +587,6 @@ ResourceCache.loadIndexBuffer = function (options) {
* @param {Number} options.imageId The image ID.
* @param {Resource} options.gltfResource The {@link Resource} containing the glTF.
* @param {Resource} options.baseResource The {@link Resource} that paths in the glTF JSON are relative to.
- * @param {SupportedImageFormats} options.supportedImageFormats The supported image formats.
*
* @returns {GltfImageLoader} The image loader.
* @private
@@ -598,14 +597,12 @@ ResourceCache.loadImage = function (options) {
var imageId = options.imageId;
var gltfResource = options.gltfResource;
var baseResource = options.baseResource;
- var supportedImageFormats = options.supportedImageFormats;
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object("options.gltf", gltf);
Check.typeOf.number("options.imageId", imageId);
Check.typeOf.object("options.gltfResource", gltfResource);
Check.typeOf.object("options.baseResource", baseResource);
- Check.typeOf.object("options.supportedImageFormats", supportedImageFormats);
//>>includeEnd('debug');
var cacheKey = ResourceCacheKey.getImageCacheKey({
@@ -613,7 +610,6 @@ ResourceCache.loadImage = function (options) {
imageId: imageId,
gltfResource: gltfResource,
baseResource: baseResource,
- supportedImageFormats: supportedImageFormats,
});
var imageLoader = ResourceCache.get(cacheKey);
@@ -627,7 +623,6 @@ ResourceCache.loadImage = function (options) {
imageId: imageId,
gltfResource: gltfResource,
baseResource: baseResource,
- supportedImageFormats: supportedImageFormats,
cacheKey: cacheKey,
});
diff --git a/Source/Scene/ResourceCacheKey.js b/Source/Scene/ResourceCacheKey.js
index 0af7bf75a66f..deaa8fc8290f 100644
--- a/Source/Scene/ResourceCacheKey.js
+++ b/Source/Scene/ResourceCacheKey.js
@@ -70,21 +70,10 @@ function getDracoCacheKey(gltf, draco, gltfResource, baseResource) {
return bufferCacheKey + "-range-" + bufferViewCacheKey;
}
-function getImageCacheKey(
- gltf,
- imageId,
- gltfResource,
- baseResource,
- supportedImageFormats
-) {
- var results = GltfLoaderUtil.getImageUriOrBufferView({
- gltf: gltf,
- imageId: imageId,
- supportedImageFormats: supportedImageFormats,
- });
-
- var bufferViewId = results.bufferViewId;
- var uri = results.uri;
+function getImageCacheKey(gltf, imageId, gltfResource, baseResource) {
+ var image = gltf.images[imageId];
+ var bufferViewId = image.bufferView;
+ var uri = image.uri;
if (defined(uri)) {
var resource = baseResource.getDerivedResource({
@@ -441,7 +430,6 @@ ResourceCacheKey.getIndexBufferCacheKey = function (options) {
* @param {Number} options.imageId The image ID.
* @param {Resource} options.gltfResource The {@link Resource} containing the glTF.
* @param {Resource} options.baseResource The {@link Resource} that paths in the glTF JSON are relative to.
- * @param {SupportedImageFormats} options.supportedImageFormats The supported image formats.
*
* @returns {String} The image cache key.
* @private
@@ -452,22 +440,19 @@ ResourceCacheKey.getImageCacheKey = function (options) {
var imageId = options.imageId;
var gltfResource = options.gltfResource;
var baseResource = options.baseResource;
- var supportedImageFormats = options.supportedImageFormats;
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object("options.gltf", gltf);
Check.typeOf.number("options.imageId", imageId);
Check.typeOf.object("options.gltfResource", gltfResource);
Check.typeOf.object("options.baseResource", baseResource);
- Check.typeOf.object("options.supportedImageFormats", supportedImageFormats);
//>>includeEnd('debug');
var imageCacheKey = getImageCacheKey(
gltf,
imageId,
gltfResource,
- baseResource,
- supportedImageFormats
+ baseResource
);
return "image:" + imageCacheKey;
@@ -514,8 +499,7 @@ ResourceCacheKey.getTextureCacheKey = function (options) {
gltf,
imageId,
gltfResource,
- baseResource,
- supportedImageFormats
+ baseResource
);
// Include the sampler cache key in the texture cache key since textures and
diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js
index 4bb114c62c9c..eed0e095698f 100644
--- a/Source/Scene/Scene.js
+++ b/Source/Scene/Scene.js
@@ -750,7 +750,7 @@ function Scene(options) {
this.sphericalHarmonicCoefficients = undefined;
/**
- * The url to the KTX file containing the specular environment map and convoluted mipmaps for image-based lighting of PBR models.
+ * The url to the KTX2 file containing the specular environment map and convoluted mipmaps for image-based lighting of PBR models.
* @type {String}
*/
this.specularEnvironmentMaps = undefined;
@@ -1695,8 +1695,14 @@ Scene.prototype.getCompressedTextureFormatSupported = function (format) {
context.s3tc) ||
((format === "WEBGL_compressed_texture_pvrtc" || format === "pvrtc") &&
context.pvrtc) ||
+ ((format === "WEBGL_compressed_texture_etc" || format === "etc") &&
+ context.etc) ||
((format === "WEBGL_compressed_texture_etc1" || format === "etc1") &&
- context.etc1)
+ context.etc1) ||
+ ((format === "WEBGL_compressed_texture_astc" || format === "astc") &&
+ context.astc) ||
+ ((format === "EXT_texture_compression_bptc" || format === "bc7") &&
+ context.bc7)
);
};
diff --git a/Source/Scene/SupportedImageFormats.js b/Source/Scene/SupportedImageFormats.js
index ed090851448b..ce95038bea1d 100644
--- a/Source/Scene/SupportedImageFormats.js
+++ b/Source/Scene/SupportedImageFormats.js
@@ -5,16 +5,12 @@ import defaultValue from "../Core/defaultValue.js";
*
* @param {Object} [options] Object with the following properties:
* @param {Boolean} [options.webp=false] Whether the browser supports WebP images.
- * @param {Boolean} [options.s3tc=false] Whether the browser supports s3tc compressed images.
- * @param {Boolean} [options.pvrtc=false] Whether the browser supports pvrtc compressed images.
- * @param {Boolean} [options.etc1=false] Whether the browser supports etc1 compressed images.
+ * @param {Boolean} [options.basis=false] Whether the browser supports compressed textures required to view KTX2 + Basis Universal images.
*
* @private
*/
export default function SupportedImageFormats(options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
this.webp = defaultValue(options.webp, false);
- this.s3tc = defaultValue(options.s3tc, false);
- this.pvrtc = defaultValue(options.pvrtc, false);
- this.etc1 = defaultValue(options.etc1, false);
+ this.basis = defaultValue(options.basis, false);
}
diff --git a/Source/Shaders/Builtin/Functions/sphericalHarmonics.glsl b/Source/Shaders/Builtin/Functions/sphericalHarmonics.glsl
index 21a2cf67b57b..71a240ebf352 100644
--- a/Source/Shaders/Builtin/Functions/sphericalHarmonics.glsl
+++ b/Source/Shaders/Builtin/Functions/sphericalHarmonics.glsl
@@ -15,12 +15,6 @@
*/
vec3 czm_sphericalHarmonics(vec3 normal, vec3 coefficients[9])
{
- const float c1 = 0.429043;
- const float c2 = 0.511664;
- const float c3 = 0.743125;
- const float c4 = 0.886227;
- const float c5 = 0.247708;
-
vec3 L00 = coefficients[0];
vec3 L1_1 = coefficients[1];
vec3 L10 = coefficients[2];
@@ -35,7 +29,14 @@ vec3 czm_sphericalHarmonics(vec3 normal, vec3 coefficients[9])
float y = normal.y;
float z = normal.z;
- return c1 * L22 * (x * x - y * y) + c3 * L20 * z * z + c4 * L00 - c5 * L20 +
- 2.0 * c1 * (L2_2 * x * y + L21 * x * z + L2_1 * y * z) +
- 2.0 * c2 * (L11 * x + L1_1 * y + L10 * z);
+ return
+ L00
+ + L1_1 * y
+ + L10 * z
+ + L11 * x
+ + L2_2 * (y * x)
+ + L2_1 * (y * z)
+ + L20 * (3.0 * z * z - 1.0)
+ + L21 * (z * x)
+ + L22 * (x * x - y * y);
}
diff --git a/Source/Shaders/OctahedralProjectionFS.glsl b/Source/Shaders/OctahedralProjectionFS.glsl
index 4b75a2ec45e9..dca8b7d8236a 100644
--- a/Source/Shaders/OctahedralProjectionFS.glsl
+++ b/Source/Shaders/OctahedralProjectionFS.glsl
@@ -3,8 +3,12 @@ uniform samplerCube cubeMap;
void main()
{
- vec4 rgbm = textureCube(cubeMap, v_cubeMapCoordinates);
- float m = rgbm.a * 16.0;
- vec3 r = rgbm.rgb * m;
- gl_FragColor = vec4(r * r, 1.0);
+ vec4 rgba = textureCube(cubeMap, v_cubeMapCoordinates);
+ #ifdef RGBA_NORMALIZED
+ gl_FragColor = vec4(rgba.rgb, 1.0);
+ #else
+ float m = rgba.a * 16.0;
+ vec3 r = rgba.rgb * m;
+ gl_FragColor = vec4(r * r, 1.0);
+ #endif
}
diff --git a/Source/ThirdParty/GltfPipeline/ForEach.js b/Source/ThirdParty/GltfPipeline/ForEach.js
index f899c88c4ad4..4ddb3e959516 100644
--- a/Source/ThirdParty/GltfPipeline/ForEach.js
+++ b/Source/ThirdParty/GltfPipeline/ForEach.js
@@ -1,73 +1,89 @@
-import usesExtension from './usesExtension.js'
-import defined from '../../Core/defined.js'
-
- /**
- * Contains traversal functions for processing elements of the glTF hierarchy.
- * @constructor
- *
- * @private
- */
- function ForEach() {
- }
-
- /**
- * Fallback for glTF 1.0
- * @private
- */
- ForEach.objectLegacy = function(objects, handler) {
- if (defined(objects)) {
- for (var objectId in objects) {
- if (Object.prototype.hasOwnProperty.call(objects, objectId)) {
- var object = objects[objectId];
- var value = handler(object, objectId);
-
- if (defined(value)) {
- return value;
- }
- }
- }
- }
- };
-
- /**
- * @private
- */
- ForEach.object = function(arrayOfObjects, handler) {
- if (defined(arrayOfObjects)) {
- var length = arrayOfObjects.length;
- for (var i = 0; i < length; i++) {
- var object = arrayOfObjects[i];
- var value = handler(object, i);
+import usesExtension from "./usesExtension.js"
+import defined from "../../Core/defined.js"
+
+/**
+ * Contains traversal functions for processing elements of the glTF hierarchy.
+ * @constructor
+ *
+ * @private
+ */
+function ForEach() {
+}
+
+/**
+ * Fallback for glTF 1.0
+ * @private
+ */
+ForEach.objectLegacy = function(objects, handler) {
+ if (defined(objects)) {
+ for (var objectId in objects) {
+ if (Object.prototype.hasOwnProperty.call(objects, objectId)) {
+ var object = objects[objectId];
+ var value = handler(object, objectId);
if (defined(value)) {
return value;
}
}
}
- };
-
- /**
- * Supports glTF 1.0 and 2.0
- * @private
- */
- ForEach.topLevel = function(gltf, name, handler) {
- var gltfProperty = gltf[name];
- if (defined(gltfProperty) && !Array.isArray(gltfProperty)) {
- return ForEach.objectLegacy(gltfProperty, handler);
+ }
+};
+
+/**
+ * @private
+ */
+ForEach.object = function(arrayOfObjects, handler) {
+ if (defined(arrayOfObjects)) {
+ var length = arrayOfObjects.length;
+ for (var i = 0; i < length; i++) {
+ var object = arrayOfObjects[i];
+ var value = handler(object, i);
+
+ if (defined(value)) {
+ return value;
+ }
}
+ }
+};
+
+/**
+ * Supports glTF 1.0 and 2.0
+ * @private
+ */
+ForEach.topLevel = function(gltf, name, handler) {
+ var gltfProperty = gltf[name];
+ if (defined(gltfProperty) && !Array.isArray(gltfProperty)) {
+ return ForEach.objectLegacy(gltfProperty, handler);
+ }
+
+ return ForEach.object(gltfProperty, handler);
+};
- return ForEach.object(gltfProperty, handler);
- };
+ForEach.accessor = function(gltf, handler) {
+ return ForEach.topLevel(gltf, 'accessors', handler);
+};
- ForEach.accessor = function(gltf, handler) {
- return ForEach.topLevel(gltf, 'accessors', handler);
- };
+ForEach.accessorWithSemantic = function(gltf, semantic, handler) {
+ var visited = {};
+ return ForEach.mesh(gltf, function(mesh) {
+ return ForEach.meshPrimitive(mesh, function(primitive) {
+ var valueForEach = ForEach.meshPrimitiveAttribute(primitive, function(accessorId, attributeSemantic) {
+ if (attributeSemantic.indexOf(semantic) === 0 && !defined(visited[accessorId])) {
+ visited[accessorId] = true;
+ var value = handler(accessorId);
- ForEach.accessorWithSemantic = function(gltf, semantic, handler) {
- var visited = {};
- return ForEach.mesh(gltf, function(mesh) {
- return ForEach.meshPrimitive(mesh, function(primitive) {
- var valueForEach = ForEach.meshPrimitiveAttribute(primitive, function(accessorId, attributeSemantic) {
+ if (defined(value)) {
+ return value;
+ }
+ }
+ });
+
+ if (defined(valueForEach)) {
+ return valueForEach;
+ }
+
+ return ForEach.meshPrimitiveTarget(primitive, function(target) {
+ return ForEach.meshPrimitiveTargetAttribute(target, function(accessorId, attributeSemantic) {
if (attributeSemantic.indexOf(semantic) === 0 && !defined(visited[accessorId])) {
visited[accessorId] = true;
var value = handler(accessorId);
@@ -77,32 +93,32 @@ import defined from '../../Core/defined.js'
}
}
});
+ });
+ });
+ });
+};
+
+ForEach.accessorContainingVertexAttributeData = function(gltf, handler) {
+ var visited = {};
+ return ForEach.mesh(gltf, function(mesh) {
+ return ForEach.meshPrimitive(mesh, function(primitive) {
+ var valueForEach = ForEach.meshPrimitiveAttribute(primitive, function(accessorId) {
+ if (!defined(visited[accessorId])) {
+ visited[accessorId] = true;
+ var value = handler(accessorId);
- if (defined(valueForEach)) {
- return valueForEach;
+ if (defined(value)) {
+ return value;
+ }
}
-
- return ForEach.meshPrimitiveTarget(primitive, function(target) {
- return ForEach.meshPrimitiveTargetAttribute(target, function(accessorId, attributeSemantic) {
- if (attributeSemantic.indexOf(semantic) === 0 && !defined(visited[accessorId])) {
- visited[accessorId] = true;
- var value = handler(accessorId);
-
- if (defined(value)) {
- return value;
- }
- }
- });
- });
});
- });
- };
- ForEach.accessorContainingVertexAttributeData = function(gltf, handler) {
- var visited = {};
- return ForEach.mesh(gltf, function(mesh) {
- return ForEach.meshPrimitive(mesh, function(primitive) {
- var valueForEach = ForEach.meshPrimitiveAttribute(primitive, function(accessorId) {
+ if (defined(valueForEach)) {
+ return valueForEach;
+ }
+
+ return ForEach.meshPrimitiveTarget(primitive, function(target) {
+ return ForEach.meshPrimitiveTargetAttribute(target, function(accessorId) {
if (!defined(visited[accessorId])) {
visited[accessorId] = true;
var value = handler(accessorId);
@@ -112,300 +128,268 @@ import defined from '../../Core/defined.js'
}
}
});
-
- if (defined(valueForEach)) {
- return valueForEach;
- }
-
- return ForEach.meshPrimitiveTarget(primitive, function(target) {
- return ForEach.meshPrimitiveTargetAttribute(target, function(accessorId) {
- if (!defined(visited[accessorId])) {
- visited[accessorId] = true;
- var value = handler(accessorId);
-
- if (defined(value)) {
- return value;
- }
- }
- });
- });
- });
- });
- };
-
- ForEach.accessorContainingIndexData = function(gltf, handler) {
- var visited = {};
- return ForEach.mesh(gltf, function(mesh) {
- return ForEach.meshPrimitive(mesh, function(primitive) {
- var indices = primitive.indices;
- if (defined(indices) && !defined(visited[indices])) {
- visited[indices] = true;
- var value = handler(indices);
-
- if (defined(value)) {
- return value;
- }
- }
});
});
- };
-
- ForEach.animation = function(gltf, handler) {
- return ForEach.topLevel(gltf, 'animations', handler);
- };
-
- ForEach.animationChannel = function(animation, handler) {
- var channels = animation.channels;
- return ForEach.object(channels, handler);
- };
-
- ForEach.animationSampler = function(animation, handler) {
- var samplers = animation.samplers;
- return ForEach.object(samplers, handler);
- };
-
- ForEach.buffer = function(gltf, handler) {
- return ForEach.topLevel(gltf, 'buffers', handler);
- };
-
- ForEach.bufferView = function(gltf, handler) {
- return ForEach.topLevel(gltf, 'bufferViews', handler);
- };
-
- ForEach.camera = function(gltf, handler) {
- return ForEach.topLevel(gltf, 'cameras', handler);
- };
-
- ForEach.image = function(gltf, handler) {
- return ForEach.topLevel(gltf, 'images', handler);
- };
-
- ForEach.compressedImage = function(image, handler) {
- if (defined(image.extras)) {
- var compressedImages = image.extras.compressedImage3DTiles;
- for (var type in compressedImages) {
- if (Object.prototype.hasOwnProperty.call(compressedImages, type)) {
- var compressedImage = compressedImages[type];
- var value = handler(compressedImage, type);
+ });
+};
+
+ForEach.accessorContainingIndexData = function(gltf, handler) {
+ var visited = {};
+ return ForEach.mesh(gltf, function(mesh) {
+ return ForEach.meshPrimitive(mesh, function(primitive) {
+ var indices = primitive.indices;
+ if (defined(indices) && !defined(visited[indices])) {
+ visited[indices] = true;
+ var value = handler(indices);
- if (defined(value)) {
- return value;
- }
+ if (defined(value)) {
+ return value;
}
}
- }
- };
+ });
+ });
+};
+
+ForEach.animation = function(gltf, handler) {
+ return ForEach.topLevel(gltf, 'animations', handler);
+};
+
+ForEach.animationChannel = function(animation, handler) {
+ var channels = animation.channels;
+ return ForEach.object(channels, handler);
+};
+
+ForEach.animationSampler = function(animation, handler) {
+ var samplers = animation.samplers;
+ return ForEach.object(samplers, handler);
+};
+
+ForEach.buffer = function(gltf, handler) {
+ return ForEach.topLevel(gltf, 'buffers', handler);
+};
+
+ForEach.bufferView = function(gltf, handler) {
+ return ForEach.topLevel(gltf, 'bufferViews', handler);
+};
+
+ForEach.camera = function(gltf, handler) {
+ return ForEach.topLevel(gltf, 'cameras', handler);
+};
+
+ForEach.image = function(gltf, handler) {
+ return ForEach.topLevel(gltf, 'images', handler);
+};
+
+ForEach.material = function(gltf, handler) {
+ return ForEach.topLevel(gltf, 'materials', handler);
+};
+
+ForEach.materialValue = function(material, handler) {
+ var values = material.values;
+ if (defined(material.extensions) && defined(material.extensions.KHR_techniques_webgl)) {
+ values = material.extensions.KHR_techniques_webgl.values;
+ }
- ForEach.material = function(gltf, handler) {
- return ForEach.topLevel(gltf, 'materials', handler);
- };
+ for (var name in values) {
+ if (Object.prototype.hasOwnProperty.call(values, name)) {
+ var value = handler(values[name], name);
- ForEach.materialValue = function(material, handler) {
- var values = material.values;
- if (defined(material.extensions) && defined(material.extensions.KHR_techniques_webgl)) {
- values = material.extensions.KHR_techniques_webgl.values;
+ if (defined(value)) {
+ return value;
+ }
}
-
- for (var name in values) {
- if (Object.prototype.hasOwnProperty.call(values, name)) {
- var value = handler(values[name], name);
-
- if (defined(value)) {
- return value;
- }
+ }
+};
+
+ForEach.mesh = function(gltf, handler) {
+ return ForEach.topLevel(gltf, 'meshes', handler);
+};
+
+ForEach.meshPrimitive = function(mesh, handler) {
+ var primitives = mesh.primitives;
+ if (defined(primitives)) {
+ var primitivesLength = primitives.length;
+ for (var i = 0; i < primitivesLength; i++) {
+ var primitive = primitives[i];
+ var value = handler(primitive, i);
+
+ if (defined(value)) {
+ return value;
}
}
- };
-
- ForEach.mesh = function(gltf, handler) {
- return ForEach.topLevel(gltf, 'meshes', handler);
- };
+ }
+};
- ForEach.meshPrimitive = function(mesh, handler) {
- var primitives = mesh.primitives;
- if (defined(primitives)) {
- var primitivesLength = primitives.length;
- for (var i = 0; i < primitivesLength; i++) {
- var primitive = primitives[i];
- var value = handler(primitive, i);
+ForEach.meshPrimitiveAttribute = function(primitive, handler) {
+ var attributes = primitive.attributes;
+ for (var semantic in attributes) {
+ if (Object.prototype.hasOwnProperty.call(attributes, semantic)) {
+ var value = handler(attributes[semantic], semantic);
- if (defined(value)) {
- return value;
- }
+ if (defined(value)) {
+ return value;
}
}
- };
+ }
+};
- ForEach.meshPrimitiveAttribute = function(primitive, handler) {
- var attributes = primitive.attributes;
- for (var semantic in attributes) {
- if (Object.prototype.hasOwnProperty.call(attributes, semantic)) {
- var value = handler(attributes[semantic], semantic);
+ForEach.meshPrimitiveTarget = function(primitive, handler) {
+ var targets = primitive.targets;
+ if (defined(targets)) {
+ var length = targets.length;
+ for (var i = 0; i < length; ++i) {
+ var value = handler(targets[i], i);
- if (defined(value)) {
- return value;
- }
+ if (defined(value)) {
+ return value;
}
}
- };
+ }
+};
- ForEach.meshPrimitiveTarget = function(primitive, handler) {
- var targets = primitive.targets;
- if (defined(targets)) {
- var length = targets.length;
- for (var i = 0; i < length; ++i) {
- var value = handler(targets[i], i);
+ForEach.meshPrimitiveTargetAttribute = function(target, handler) {
+ for (var semantic in target) {
+ if (Object.prototype.hasOwnProperty.call(target, semantic)) {
+ var accessorId = target[semantic];
+ var value = handler(accessorId, semantic);
- if (defined(value)) {
- return value;
- }
+ if (defined(value)) {
+ return value;
}
}
- };
-
- ForEach.meshPrimitiveTargetAttribute = function(target, handler) {
- for (var semantic in target) {
- if (Object.prototype.hasOwnProperty.call(target, semantic)) {
- var accessorId = target[semantic];
- var value = handler(accessorId, semantic);
+ }
+};
+
+ForEach.node = function(gltf, handler) {
+ return ForEach.topLevel(gltf, 'nodes', handler);
+};
+
+ForEach.nodeInTree = function(gltf, nodeIds, handler) {
+ var nodes = gltf.nodes;
+ if (defined(nodes)) {
+ var length = nodeIds.length;
+ for (var i = 0; i < length; i++) {
+ var nodeId = nodeIds[i];
+ var node = nodes[nodeId];
+ if (defined(node)) {
+ var value = handler(node, nodeId);
if (defined(value)) {
return value;
}
- }
- }
- };
-
- ForEach.node = function(gltf, handler) {
- return ForEach.topLevel(gltf, 'nodes', handler);
- };
-
- ForEach.nodeInTree = function(gltf, nodeIds, handler) {
- var nodes = gltf.nodes;
- if (defined(nodes)) {
- var length = nodeIds.length;
- for (var i = 0; i < length; i++) {
- var nodeId = nodeIds[i];
- var node = nodes[nodeId];
- if (defined(node)) {
- var value = handler(node, nodeId);
+
+ var children = node.children;
+ if (defined(children)) {
+ value = ForEach.nodeInTree(gltf, children, handler);
if (defined(value)) {
return value;
}
-
- var children = node.children;
- if (defined(children)) {
- value = ForEach.nodeInTree(gltf, children, handler);
-
- if (defined(value)) {
- return value;
- }
- }
}
}
}
- };
+ }
+};
- ForEach.nodeInScene = function(gltf, scene, handler) {
- var sceneNodeIds = scene.nodes;
- if (defined(sceneNodeIds)) {
- return ForEach.nodeInTree(gltf, sceneNodeIds, handler);
- }
- };
+ForEach.nodeInScene = function(gltf, scene, handler) {
+ var sceneNodeIds = scene.nodes;
+ if (defined(sceneNodeIds)) {
+ return ForEach.nodeInTree(gltf, sceneNodeIds, handler);
+ }
+};
- ForEach.program = function(gltf, handler) {
- if (usesExtension(gltf, 'KHR_techniques_webgl')) {
- return ForEach.object(gltf.extensions.KHR_techniques_webgl.programs, handler);
- }
+ForEach.program = function(gltf, handler) {
+ if (usesExtension(gltf, 'KHR_techniques_webgl')) {
+ return ForEach.object(gltf.extensions.KHR_techniques_webgl.programs, handler);
+ }
- return ForEach.topLevel(gltf, 'programs', handler);
- };
+ return ForEach.topLevel(gltf, 'programs', handler);
+};
- ForEach.sampler = function(gltf, handler) {
- return ForEach.topLevel(gltf, 'samplers', handler);
- };
+ForEach.sampler = function(gltf, handler) {
+ return ForEach.topLevel(gltf, 'samplers', handler);
+};
- ForEach.scene = function(gltf, handler) {
- return ForEach.topLevel(gltf, 'scenes', handler);
- };
+ForEach.scene = function(gltf, handler) {
+ return ForEach.topLevel(gltf, 'scenes', handler);
+};
- ForEach.shader = function(gltf, handler) {
- if (usesExtension(gltf, 'KHR_techniques_webgl')) {
- return ForEach.object(gltf.extensions.KHR_techniques_webgl.shaders, handler);
- }
+ForEach.shader = function(gltf, handler) {
+ if (usesExtension(gltf, 'KHR_techniques_webgl')) {
+ return ForEach.object(gltf.extensions.KHR_techniques_webgl.shaders, handler);
+ }
- return ForEach.topLevel(gltf, 'shaders', handler);
- };
+ return ForEach.topLevel(gltf, 'shaders', handler);
+};
- ForEach.skin = function(gltf, handler) {
- return ForEach.topLevel(gltf, 'skins', handler);
- };
+ForEach.skin = function(gltf, handler) {
+ return ForEach.topLevel(gltf, 'skins', handler);
+};
- ForEach.skinJoint = function(skin, handler) {
- var joints = skin.joints;
- if (defined(joints)) {
- var jointsLength = joints.length;
- for (var i = 0; i < jointsLength; i++) {
- var joint = joints[i];
- var value = handler(joint);
+ForEach.skinJoint = function(skin, handler) {
+ var joints = skin.joints;
+ if (defined(joints)) {
+ var jointsLength = joints.length;
+ for (var i = 0; i < jointsLength; i++) {
+ var joint = joints[i];
+ var value = handler(joint);
- if (defined(value)) {
- return value;
- }
+ if (defined(value)) {
+ return value;
}
}
- };
+ }
+};
- ForEach.techniqueAttribute = function(technique, handler) {
- var attributes = technique.attributes;
- for (var attributeName in attributes) {
- if (Object.prototype.hasOwnProperty.call(attributes, attributeName)) {
- var value = handler(attributes[attributeName], attributeName);
+ForEach.techniqueAttribute = function(technique, handler) {
+ var attributes = technique.attributes;
+ for (var attributeName in attributes) {
+ if (Object.prototype.hasOwnProperty.call(attributes, attributeName)) {
+ var value = handler(attributes[attributeName], attributeName);
- if (defined(value)) {
- return value;
- }
+ if (defined(value)) {
+ return value;
}
}
- };
+ }
+};
- ForEach.techniqueUniform = function(technique, handler) {
- var uniforms = technique.uniforms;
- for (var uniformName in uniforms) {
- if (Object.prototype.hasOwnProperty.call(uniforms, uniformName)) {
- var value = handler(uniforms[uniformName], uniformName);
+ForEach.techniqueUniform = function(technique, handler) {
+ var uniforms = technique.uniforms;
+ for (var uniformName in uniforms) {
+ if (Object.prototype.hasOwnProperty.call(uniforms, uniformName)) {
+ var value = handler(uniforms[uniformName], uniformName);
- if (defined(value)) {
- return value;
- }
+ if (defined(value)) {
+ return value;
}
}
- };
+ }
+};
- ForEach.techniqueParameter = function(technique, handler) {
- var parameters = technique.parameters;
- for (var parameterName in parameters) {
- if (Object.prototype.hasOwnProperty.call(parameters, parameterName)) {
- var value = handler(parameters[parameterName], parameterName);
+ForEach.techniqueParameter = function(technique, handler) {
+ var parameters = technique.parameters;
+ for (var parameterName in parameters) {
+ if (Object.prototype.hasOwnProperty.call(parameters, parameterName)) {
+ var value = handler(parameters[parameterName], parameterName);
- if (defined(value)) {
- return value;
- }
+ if (defined(value)) {
+ return value;
}
}
- };
+ }
+};
- ForEach.technique = function(gltf, handler) {
- if (usesExtension(gltf, 'KHR_techniques_webgl')) {
- return ForEach.object(gltf.extensions.KHR_techniques_webgl.techniques, handler);
- }
+ForEach.technique = function(gltf, handler) {
+ if (usesExtension(gltf, 'KHR_techniques_webgl')) {
+ return ForEach.object(gltf.extensions.KHR_techniques_webgl.techniques, handler);
+ }
- return ForEach.topLevel(gltf, 'techniques', handler);
- };
+ return ForEach.topLevel(gltf, 'techniques', handler);
+};
- ForEach.texture = function(gltf, handler) {
- return ForEach.topLevel(gltf, 'textures', handler);
- };
+ForEach.texture = function(gltf, handler) {
+ return ForEach.topLevel(gltf, 'textures', handler);
+};
- export default ForEach;
+export default ForEach;
diff --git a/Source/ThirdParty/GltfPipeline/addBuffer.js b/Source/ThirdParty/GltfPipeline/addBuffer.js
index 1f4041327164..3db4b61acc8b 100644
--- a/Source/ThirdParty/GltfPipeline/addBuffer.js
+++ b/Source/ThirdParty/GltfPipeline/addBuffer.js
@@ -1,30 +1,30 @@
-import addToArray from './addToArray.js'
+import addToArray from "./addToArray.js"
- /**
- * Adds buffer to gltf.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @param {Buffer} buffer A Buffer object which will be added to gltf.buffers.
- * @returns {Number} The bufferView id of the newly added bufferView.
- *
- * @private
- */
- function addBuffer(gltf, buffer) {
- var newBuffer = {
- byteLength: buffer.length,
- extras: {
- _pipeline: {
- source: buffer
- }
+/**
+ * Adds buffer to gltf.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @param {Buffer} buffer A Buffer object which will be added to gltf.buffers.
+ * @returns {Number} The bufferView id of the newly added bufferView.
+ *
+ * @private
+ */
+function addBuffer(gltf, buffer) {
+ var newBuffer = {
+ byteLength: buffer.length,
+ extras: {
+ _pipeline: {
+ source: buffer
}
- };
- var bufferId = addToArray(gltf.buffers, newBuffer);
- var bufferView = {
- buffer: bufferId,
- byteOffset: 0,
- byteLength: buffer.length
- };
- return addToArray(gltf.bufferViews, bufferView);
- }
+ }
+ };
+ var bufferId = addToArray(gltf.buffers, newBuffer);
+ var bufferView = {
+ buffer: bufferId,
+ byteOffset: 0,
+ byteLength: buffer.length
+ };
+ return addToArray(gltf.bufferViews, bufferView);
+}
- export default addBuffer;
+export default addBuffer;
diff --git a/Source/ThirdParty/GltfPipeline/addDefaults.js b/Source/ThirdParty/GltfPipeline/addDefaults.js
index 231d955836c5..43b95a3d7dcb 100644
--- a/Source/ThirdParty/GltfPipeline/addDefaults.js
+++ b/Source/ThirdParty/GltfPipeline/addDefaults.js
@@ -1,181 +1,181 @@
-import addToArray from './addToArray.js'
-import ForEach from './ForEach.js'
-import getAccessorByteStride from './getAccessorByteStride.js'
-import defaultValue from '../../Core/defaultValue.js'
-import defined from '../../Core/defined.js'
-import WebGLConstants from '../../Core/WebGLConstants.js'
-
- /**
- * Adds default glTF values if they don't exist.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @returns {Object} The modified glTF.
- *
- * @private
- */
- function addDefaults(gltf) {
- ForEach.accessor(gltf, function(accessor) {
- if (defined(accessor.bufferView)) {
- accessor.byteOffset = defaultValue(accessor.byteOffset, 0);
- }
- });
-
- ForEach.bufferView(gltf, function(bufferView) {
- if (defined(bufferView.buffer)) {
- bufferView.byteOffset = defaultValue(bufferView.byteOffset, 0);
- }
- });
+import addToArray from "./addToArray.js"
+import ForEach from "./ForEach.js"
+import getAccessorByteStride from "./getAccessorByteStride.js"
+import defaultValue from "../../Core/defaultValue.js"
+import defined from "../../Core/defined.js"
+import WebGLConstants from "../../Core/WebGLConstants.js"
+
+/**
+ * Adds default glTF values if they don't exist.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @returns {Object} The modified glTF.
+ *
+ * @private
+ */
+function addDefaults(gltf) {
+ ForEach.accessor(gltf, function(accessor) {
+ if (defined(accessor.bufferView)) {
+ accessor.byteOffset = defaultValue(accessor.byteOffset, 0);
+ }
+ });
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- primitive.mode = defaultValue(primitive.mode, WebGLConstants.TRIANGLES);
- if (!defined(primitive.material)) {
- if (!defined(gltf.materials)) {
- gltf.materials = [];
- }
- var defaultMaterial = {
- name: 'default'
- };
- primitive.material = addToArray(gltf.materials, defaultMaterial);
+ ForEach.bufferView(gltf, function(bufferView) {
+ if (defined(bufferView.buffer)) {
+ bufferView.byteOffset = defaultValue(bufferView.byteOffset, 0);
+ }
+ });
+
+ ForEach.mesh(gltf, function(mesh) {
+ ForEach.meshPrimitive(mesh, function(primitive) {
+ primitive.mode = defaultValue(primitive.mode, WebGLConstants.TRIANGLES);
+ if (!defined(primitive.material)) {
+ if (!defined(gltf.materials)) {
+ gltf.materials = [];
}
- });
- });
-
- ForEach.accessorContainingVertexAttributeData(gltf, function(accessorId) {
- var accessor = gltf.accessors[accessorId];
- var bufferViewId = accessor.bufferView;
- accessor.normalized = defaultValue(accessor.normalized, false);
- if (defined(bufferViewId)) {
- var bufferView = gltf.bufferViews[bufferViewId];
- bufferView.byteStride = getAccessorByteStride(gltf, accessor);
- bufferView.target = WebGLConstants.ARRAY_BUFFER;
+ var defaultMaterial = {
+ name: 'default'
+ };
+ primitive.material = addToArray(gltf.materials, defaultMaterial);
}
});
-
- ForEach.accessorContainingIndexData(gltf, function(accessorId) {
- var accessor = gltf.accessors[accessorId];
- var bufferViewId = accessor.bufferView;
- if (defined(bufferViewId)) {
- var bufferView = gltf.bufferViews[bufferViewId];
- bufferView.target = WebGLConstants.ELEMENT_ARRAY_BUFFER;
- }
- });
-
- ForEach.material(gltf, function(material) {
- var extensions = defaultValue(material.extensions, defaultValue.EMPTY_OBJECT);
- var materialsCommon = extensions.KHR_materials_common;
- if (defined(materialsCommon)) {
- var technique = materialsCommon.technique;
- var values = defined(materialsCommon.values) ? materialsCommon.values : {};
- materialsCommon.values = values;
-
- values.ambient = defined(values.ambient) ? values.ambient : [0.0, 0.0, 0.0, 1.0];
- values.emission = defined(values.emission) ? values.emission : [0.0, 0.0, 0.0, 1.0];
-
- values.transparency = defaultValue(values.transparency, 1.0);
- values.transparent = defaultValue(values.transparent, false);
- values.doubleSided = defaultValue(values.doubleSided, false);
-
- if (technique !== 'CONSTANT') {
- values.diffuse = defined(values.diffuse) ? values.diffuse : [0.0, 0.0, 0.0, 1.0];
- if (technique !== 'LAMBERT') {
- values.specular = defined(values.specular) ? values.specular : [0.0, 0.0, 0.0, 1.0];
- values.shininess = defaultValue(values.shininess, 0.0);
- }
+ });
+
+ ForEach.accessorContainingVertexAttributeData(gltf, function(accessorId) {
+ var accessor = gltf.accessors[accessorId];
+ var bufferViewId = accessor.bufferView;
+ accessor.normalized = defaultValue(accessor.normalized, false);
+ if (defined(bufferViewId)) {
+ var bufferView = gltf.bufferViews[bufferViewId];
+ bufferView.byteStride = getAccessorByteStride(gltf, accessor);
+ bufferView.target = WebGLConstants.ARRAY_BUFFER;
+ }
+ });
+
+ ForEach.accessorContainingIndexData(gltf, function(accessorId) {
+ var accessor = gltf.accessors[accessorId];
+ var bufferViewId = accessor.bufferView;
+ if (defined(bufferViewId)) {
+ var bufferView = gltf.bufferViews[bufferViewId];
+ bufferView.target = WebGLConstants.ELEMENT_ARRAY_BUFFER;
+ }
+ });
+
+ ForEach.material(gltf, function(material) {
+ var extensions = defaultValue(material.extensions, defaultValue.EMPTY_OBJECT);
+ var materialsCommon = extensions.KHR_materials_common;
+ if (defined(materialsCommon)) {
+ var technique = materialsCommon.technique;
+ var values = defined(materialsCommon.values) ? materialsCommon.values : {};
+ materialsCommon.values = values;
+
+ values.ambient = defined(values.ambient) ? values.ambient : [0.0, 0.0, 0.0, 1.0];
+ values.emission = defined(values.emission) ? values.emission : [0.0, 0.0, 0.0, 1.0];
+
+ values.transparency = defaultValue(values.transparency, 1.0);
+ values.transparent = defaultValue(values.transparent, false);
+ values.doubleSided = defaultValue(values.doubleSided, false);
+
+ if (technique !== 'CONSTANT') {
+ values.diffuse = defined(values.diffuse) ? values.diffuse : [0.0, 0.0, 0.0, 1.0];
+ if (technique !== 'LAMBERT') {
+ values.specular = defined(values.specular) ? values.specular : [0.0, 0.0, 0.0, 1.0];
+ values.shininess = defaultValue(values.shininess, 0.0);
}
- return;
- }
-
- material.emissiveFactor = defaultValue(material.emissiveFactor, [0.0, 0.0, 0.0]);
- material.alphaMode = defaultValue(material.alphaMode, 'OPAQUE');
- material.doubleSided = defaultValue(material.doubleSided, false);
-
- if (material.alphaMode === 'MASK') {
- material.alphaCutoff = defaultValue(material.alphaCutoff, 0.5);
- }
-
- var techniquesExtension = extensions.KHR_techniques_webgl;
- if (defined(techniquesExtension)) {
- ForEach.materialValue(material, function (materialValue) {
- // Check if material value is a TextureInfo object
- if (defined(materialValue.index)) {
- addTextureDefaults(materialValue);
- }
- });
}
+ return;
+ }
- addTextureDefaults(material.emissiveTexture);
- addTextureDefaults(material.normalTexture);
- addTextureDefaults(material.occlusionTexture);
-
- var pbrMetallicRoughness = material.pbrMetallicRoughness;
- if (defined(pbrMetallicRoughness)) {
- pbrMetallicRoughness.baseColorFactor = defaultValue(pbrMetallicRoughness.baseColorFactor, [1.0, 1.0, 1.0, 1.0]);
- pbrMetallicRoughness.metallicFactor = defaultValue(pbrMetallicRoughness.metallicFactor, 1.0);
- pbrMetallicRoughness.roughnessFactor = defaultValue(pbrMetallicRoughness.roughnessFactor, 1.0);
- addTextureDefaults(pbrMetallicRoughness.baseColorTexture);
- addTextureDefaults(pbrMetallicRoughness.metallicRoughnessTexture);
- }
+ material.emissiveFactor = defaultValue(material.emissiveFactor, [0.0, 0.0, 0.0]);
+ material.alphaMode = defaultValue(material.alphaMode, 'OPAQUE');
+ material.doubleSided = defaultValue(material.doubleSided, false);
- var pbrSpecularGlossiness = extensions.KHR_materials_pbrSpecularGlossiness;
- if (defined(pbrSpecularGlossiness)) {
- pbrSpecularGlossiness.diffuseFactor = defaultValue(pbrSpecularGlossiness.diffuseFactor, [1.0, 1.0, 1.0, 1.0]);
- pbrSpecularGlossiness.specularFactor = defaultValue(pbrSpecularGlossiness.specularFactor, [1.0, 1.0, 1.0]);
- pbrSpecularGlossiness.glossinessFactor = defaultValue(pbrSpecularGlossiness.glossinessFactor, 1.0);
- addTextureDefaults(pbrSpecularGlossiness.specularGlossinessTexture);
- }
- });
+ if (material.alphaMode === 'MASK') {
+ material.alphaCutoff = defaultValue(material.alphaCutoff, 0.5);
+ }
- ForEach.animation(gltf, function(animation) {
- ForEach.animationSampler(animation, function(sampler) {
- sampler.interpolation = defaultValue(sampler.interpolation, 'LINEAR');
+ var techniquesExtension = extensions.KHR_techniques_webgl;
+ if (defined(techniquesExtension)) {
+ ForEach.materialValue(material, function (materialValue) {
+ // Check if material value is a TextureInfo object
+ if (defined(materialValue.index)) {
+ addTextureDefaults(materialValue);
+ }
});
- });
+ }
- var animatedNodes = getAnimatedNodes(gltf);
- ForEach.node(gltf, function(node, id) {
- var animated = defined(animatedNodes[id]);
- if (animated || defined(node.translation) || defined(node.rotation) || defined(node.scale)) {
- node.translation = defaultValue(node.translation, [0.0, 0.0, 0.0]);
- node.rotation = defaultValue(node.rotation, [0.0, 0.0, 0.0, 1.0]);
- node.scale = defaultValue(node.scale, [1.0, 1.0, 1.0]);
- } else {
- node.matrix = defaultValue(node.matrix, [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]);
- }
- });
+ addTextureDefaults(material.emissiveTexture);
+ addTextureDefaults(material.normalTexture);
+ addTextureDefaults(material.occlusionTexture);
+
+ var pbrMetallicRoughness = material.pbrMetallicRoughness;
+ if (defined(pbrMetallicRoughness)) {
+ pbrMetallicRoughness.baseColorFactor = defaultValue(pbrMetallicRoughness.baseColorFactor, [1.0, 1.0, 1.0, 1.0]);
+ pbrMetallicRoughness.metallicFactor = defaultValue(pbrMetallicRoughness.metallicFactor, 1.0);
+ pbrMetallicRoughness.roughnessFactor = defaultValue(pbrMetallicRoughness.roughnessFactor, 1.0);
+ addTextureDefaults(pbrMetallicRoughness.baseColorTexture);
+ addTextureDefaults(pbrMetallicRoughness.metallicRoughnessTexture);
+ }
- ForEach.sampler(gltf, function(sampler) {
- sampler.wrapS = defaultValue(sampler.wrapS, WebGLConstants.REPEAT);
- sampler.wrapT = defaultValue(sampler.wrapT, WebGLConstants.REPEAT);
- });
+ var pbrSpecularGlossiness = extensions.KHR_materials_pbrSpecularGlossiness;
+ if (defined(pbrSpecularGlossiness)) {
+ pbrSpecularGlossiness.diffuseFactor = defaultValue(pbrSpecularGlossiness.diffuseFactor, [1.0, 1.0, 1.0, 1.0]);
+ pbrSpecularGlossiness.specularFactor = defaultValue(pbrSpecularGlossiness.specularFactor, [1.0, 1.0, 1.0]);
+ pbrSpecularGlossiness.glossinessFactor = defaultValue(pbrSpecularGlossiness.glossinessFactor, 1.0);
+ addTextureDefaults(pbrSpecularGlossiness.specularGlossinessTexture);
+ }
+ });
- if (defined(gltf.scenes) && !defined(gltf.scene)) {
- gltf.scene = 0;
+ ForEach.animation(gltf, function(animation) {
+ ForEach.animationSampler(animation, function(sampler) {
+ sampler.interpolation = defaultValue(sampler.interpolation, 'LINEAR');
+ });
+ });
+
+ var animatedNodes = getAnimatedNodes(gltf);
+ ForEach.node(gltf, function(node, id) {
+ var animated = defined(animatedNodes[id]);
+ if (animated || defined(node.translation) || defined(node.rotation) || defined(node.scale)) {
+ node.translation = defaultValue(node.translation, [0.0, 0.0, 0.0]);
+ node.rotation = defaultValue(node.rotation, [0.0, 0.0, 0.0, 1.0]);
+ node.scale = defaultValue(node.scale, [1.0, 1.0, 1.0]);
+ } else {
+ node.matrix = defaultValue(node.matrix, [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]);
}
+ });
+
+ ForEach.sampler(gltf, function(sampler) {
+ sampler.wrapS = defaultValue(sampler.wrapS, WebGLConstants.REPEAT);
+ sampler.wrapT = defaultValue(sampler.wrapT, WebGLConstants.REPEAT);
+ });
- return gltf;
+ if (defined(gltf.scenes) && !defined(gltf.scene)) {
+ gltf.scene = 0;
}
- function getAnimatedNodes(gltf) {
- var nodes = {};
- ForEach.animation(gltf, function(animation) {
- ForEach.animationChannel(animation, function(channel) {
- var target = channel.target;
- var nodeId = target.node;
- var path = target.path;
- // Ignore animations that target 'weights'
- if (path === 'translation' || path === 'rotation' || path === 'scale') {
- nodes[nodeId] = true;
- }
- });
+ return gltf;
+}
+
+function getAnimatedNodes(gltf) {
+ var nodes = {};
+ ForEach.animation(gltf, function(animation) {
+ ForEach.animationChannel(animation, function(channel) {
+ var target = channel.target;
+ var nodeId = target.node;
+ var path = target.path;
+ // Ignore animations that target 'weights'
+ if (path === 'translation' || path === 'rotation' || path === 'scale') {
+ nodes[nodeId] = true;
+ }
});
- return nodes;
- }
+ });
+ return nodes;
+}
- function addTextureDefaults(texture) {
- if (defined(texture)) {
- texture.texCoord = defaultValue(texture.texCoord, 0);
- }
+function addTextureDefaults(texture) {
+ if (defined(texture)) {
+ texture.texCoord = defaultValue(texture.texCoord, 0);
}
+}
- export default addDefaults;
+export default addDefaults;
diff --git a/Source/ThirdParty/GltfPipeline/addExtensionsRequired.js b/Source/ThirdParty/GltfPipeline/addExtensionsRequired.js
index c830658845e8..a0c605a92240 100644
--- a/Source/ThirdParty/GltfPipeline/addExtensionsRequired.js
+++ b/Source/ThirdParty/GltfPipeline/addExtensionsRequired.js
@@ -1,24 +1,24 @@
-import addExtensionsUsed from './addExtensionsUsed.js'
-import addToArray from './addToArray.js'
-import defined from '../../Core/defined.js'
+import addExtensionsUsed from "./addExtensionsUsed.js"
+import addToArray from "./addToArray.js"
+import defined from "../../Core/defined.js"
- /**
- * Adds an extension to gltf.extensionsRequired if it does not already exist.
- * Initializes extensionsRequired if it is not defined.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @param {String} extension The extension to add.
- *
- * @private
- */
- function addExtensionsRequired(gltf, extension) {
- var extensionsRequired = gltf.extensionsRequired;
- if (!defined(extensionsRequired)) {
- extensionsRequired = [];
- gltf.extensionsRequired = extensionsRequired;
- }
- addToArray(extensionsRequired, extension, true);
- addExtensionsUsed(gltf, extension);
+/**
+ * Adds an extension to gltf.extensionsRequired if it does not already exist.
+ * Initializes extensionsRequired if it is not defined.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @param {String} extension The extension to add.
+ *
+ * @private
+ */
+function addExtensionsRequired(gltf, extension) {
+ var extensionsRequired = gltf.extensionsRequired;
+ if (!defined(extensionsRequired)) {
+ extensionsRequired = [];
+ gltf.extensionsRequired = extensionsRequired;
}
+ addToArray(extensionsRequired, extension, true);
+ addExtensionsUsed(gltf, extension);
+}
- export default addExtensionsRequired;
+export default addExtensionsRequired;
diff --git a/Source/ThirdParty/GltfPipeline/addExtensionsUsed.js b/Source/ThirdParty/GltfPipeline/addExtensionsUsed.js
index 9c3d53db788b..d035ace73996 100644
--- a/Source/ThirdParty/GltfPipeline/addExtensionsUsed.js
+++ b/Source/ThirdParty/GltfPipeline/addExtensionsUsed.js
@@ -1,22 +1,22 @@
-import addToArray from './addToArray.js'
-import defined from '../../Core/defined.js'
+import addToArray from "./addToArray.js"
+import defined from "../../Core/defined.js"
- /**
- * Adds an extension to gltf.extensionsUsed if it does not already exist.
- * Initializes extensionsUsed if it is not defined.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @param {String} extension The extension to add.
- *
- * @private
- */
- function addExtensionsUsed(gltf, extension) {
- var extensionsUsed = gltf.extensionsUsed;
- if (!defined(extensionsUsed)) {
- extensionsUsed = [];
- gltf.extensionsUsed = extensionsUsed;
- }
- addToArray(extensionsUsed, extension, true);
+/**
+ * Adds an extension to gltf.extensionsUsed if it does not already exist.
+ * Initializes extensionsUsed if it is not defined.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @param {String} extension The extension to add.
+ *
+ * @private
+ */
+function addExtensionsUsed(gltf, extension) {
+ var extensionsUsed = gltf.extensionsUsed;
+ if (!defined(extensionsUsed)) {
+ extensionsUsed = [];
+ gltf.extensionsUsed = extensionsUsed;
}
+ addToArray(extensionsUsed, extension, true);
+}
- export default addExtensionsUsed;
+export default addExtensionsUsed;
diff --git a/Source/ThirdParty/GltfPipeline/addPipelineExtras.js b/Source/ThirdParty/GltfPipeline/addPipelineExtras.js
index 2fb06c36bf41..91eb2df1e4aa 100644
--- a/Source/ThirdParty/GltfPipeline/addPipelineExtras.js
+++ b/Source/ThirdParty/GltfPipeline/addPipelineExtras.js
@@ -1,37 +1,34 @@
-import ForEach from './ForEach.js'
-import defined from '../../Core/defined.js'
+import ForEach from "./ForEach.js"
+import defined from "../../Core/defined.js"
- /**
- * Adds extras._pipeline to each object that can have extras in the glTF asset.
- * This stage runs before updateVersion and handles both glTF 1.0 and glTF 2.0 assets.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @returns {Object} The glTF asset with the added pipeline extras.
- *
- * @private
- */
- function addPipelineExtras(gltf) {
- ForEach.shader(gltf, function(shader) {
- addExtras(shader);
- });
- ForEach.buffer(gltf, function(buffer) {
- addExtras(buffer);
- });
- ForEach.image(gltf, function (image) {
- addExtras(image);
- ForEach.compressedImage(image, function(compressedImage) {
- addExtras(compressedImage);
- });
- });
+/**
+ * Adds extras._pipeline to each object that can have extras in the glTF asset.
+ * This stage runs before updateVersion and handles both glTF 1.0 and glTF 2.0 assets.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @returns {Object} The glTF asset with the added pipeline extras.
+ *
+ * @private
+ */
+function addPipelineExtras(gltf) {
+ ForEach.shader(gltf, function(shader) {
+ addExtras(shader);
+ });
+ ForEach.buffer(gltf, function(buffer) {
+ addExtras(buffer);
+ });
+ ForEach.image(gltf, function (image) {
+ addExtras(image);
+ });
- addExtras(gltf);
+ addExtras(gltf);
- return gltf;
- }
+ return gltf;
+}
- function addExtras(object) {
- object.extras = defined(object.extras) ? object.extras : {};
- object.extras._pipeline = defined(object.extras._pipeline) ? object.extras._pipeline : {};
- }
+function addExtras(object) {
+ object.extras = defined(object.extras) ? object.extras : {};
+ object.extras._pipeline = defined(object.extras._pipeline) ? object.extras._pipeline : {};
+}
- export default addPipelineExtras;
+export default addPipelineExtras;
diff --git a/Source/ThirdParty/GltfPipeline/addToArray.js b/Source/ThirdParty/GltfPipeline/addToArray.js
index 7e102eeba7ae..8f487e825598 100644
--- a/Source/ThirdParty/GltfPipeline/addToArray.js
+++ b/Source/ThirdParty/GltfPipeline/addToArray.js
@@ -1,25 +1,25 @@
-import defaultValue from '../../Core/defaultValue.js'
+import defaultValue from "../../Core/defaultValue.js"
- /**
- * Adds an element to an array and returns the element's index.
- *
- * @param {Array} array The array to add to.
- * @param {Object} element The element to add.
- * @param {Boolean} [checkDuplicates=false] When true
, if a duplicate element is found its index is returned and element
is not added to the array.
- *
- * @private
- */
- function addToArray(array, element, checkDuplicates) {
- checkDuplicates = defaultValue(checkDuplicates, false);
- if (checkDuplicates) {
- var index = array.indexOf(element);
- if (index > -1) {
- return index;
- }
+/**
+ * Adds an element to an array and returns the element's index.
+ *
+ * @param {Array} array The array to add to.
+ * @param {Object} element The element to add.
+ * @param {Boolean} [checkDuplicates=false] When true
, if a duplicate element is found its index is returned and element
is not added to the array.
+ *
+ * @private
+ */
+function addToArray(array, element, checkDuplicates) {
+ checkDuplicates = defaultValue(checkDuplicates, false);
+ if (checkDuplicates) {
+ var index = array.indexOf(element);
+ if (index > -1) {
+ return index;
}
-
- array.push(element);
- return array.length - 1;
}
- export default addToArray;
+ array.push(element);
+ return array.length - 1;
+}
+
+export default addToArray;
diff --git a/Source/ThirdParty/GltfPipeline/findAccessorMinMax.js b/Source/ThirdParty/GltfPipeline/findAccessorMinMax.js
index 721415f37240..ecf17b706171 100644
--- a/Source/ThirdParty/GltfPipeline/findAccessorMinMax.js
+++ b/Source/ThirdParty/GltfPipeline/findAccessorMinMax.js
@@ -1,64 +1,64 @@
-import getAccessorByteStride from './getAccessorByteStride.js'
-import getComponentReader from './getComponentReader.js'
-import numberOfComponentsForType from './numberOfComponentsForType.js'
-import arrayFill from '../../Core/arrayFill.js'
-import ComponentDatatype from '../../Core/ComponentDatatype.js'
-import defined from '../../Core/defined.js'
+import getAccessorByteStride from "./getAccessorByteStride.js"
+import getComponentReader from "./getComponentReader.js"
+import numberOfComponentsForType from "./numberOfComponentsForType.js"
+import arrayFill from "../../Core/arrayFill.js"
+import ComponentDatatype from "../../Core/ComponentDatatype.js"
+import defined from "../../Core/defined.js"
- /**
- * Finds the min and max values of the accessor.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @param {Object} accessor The accessor object from the glTF asset to read.
- * @returns {{min: Array, max: Array}} min holding the array of minimum values and max holding the array of maximum values.
- *
- * @private
- */
- function findAccessorMinMax(gltf, accessor) {
- var bufferViews = gltf.bufferViews;
- var buffers = gltf.buffers;
- var bufferViewId = accessor.bufferView;
- var numberOfComponents = numberOfComponentsForType(accessor.type);
+/**
+ * Finds the min and max values of the accessor.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @param {Object} accessor The accessor object from the glTF asset to read.
+ * @returns {{min: Array, max: Array}} min holding the array of minimum values and max holding the array of maximum values.
+ *
+ * @private
+ */
+function findAccessorMinMax(gltf, accessor) {
+ var bufferViews = gltf.bufferViews;
+ var buffers = gltf.buffers;
+ var bufferViewId = accessor.bufferView;
+ var numberOfComponents = numberOfComponentsForType(accessor.type);
- // According to the spec, when bufferView is not defined, accessor must be initialized with zeros
- if (!defined(accessor.bufferView)) {
- return {
- min: arrayFill(new Array(numberOfComponents), 0.0),
- max: arrayFill(new Array(numberOfComponents), 0.0)
- };
- }
+ // According to the spec, when bufferView is not defined, accessor must be initialized with zeros
+ if (!defined(accessor.bufferView)) {
+ return {
+ min: arrayFill(new Array(numberOfComponents), 0.0),
+ max: arrayFill(new Array(numberOfComponents), 0.0)
+ };
+ }
- var min = arrayFill(new Array(numberOfComponents), Number.POSITIVE_INFINITY);
- var max = arrayFill(new Array(numberOfComponents), Number.NEGATIVE_INFINITY);
+ var min = arrayFill(new Array(numberOfComponents), Number.POSITIVE_INFINITY);
+ var max = arrayFill(new Array(numberOfComponents), Number.NEGATIVE_INFINITY);
- var bufferView = bufferViews[bufferViewId];
- var bufferId = bufferView.buffer;
- var buffer = buffers[bufferId];
- var source = buffer.extras._pipeline.source;
+ var bufferView = bufferViews[bufferViewId];
+ var bufferId = bufferView.buffer;
+ var buffer = buffers[bufferId];
+ var source = buffer.extras._pipeline.source;
- var count = accessor.count;
- var byteStride = getAccessorByteStride(gltf, accessor);
- var byteOffset = accessor.byteOffset + bufferView.byteOffset + source.byteOffset;
- var componentType = accessor.componentType;
- var componentTypeByteLength = ComponentDatatype.getSizeInBytes(componentType);
- var dataView = new DataView(source.buffer);
- var components = new Array(numberOfComponents);
- var componentReader = getComponentReader(componentType);
+ var count = accessor.count;
+ var byteStride = getAccessorByteStride(gltf, accessor);
+ var byteOffset = accessor.byteOffset + bufferView.byteOffset + source.byteOffset;
+ var componentType = accessor.componentType;
+ var componentTypeByteLength = ComponentDatatype.getSizeInBytes(componentType);
+ var dataView = new DataView(source.buffer);
+ var components = new Array(numberOfComponents);
+ var componentReader = getComponentReader(componentType);
- for (var i = 0; i < count; i++) {
- componentReader(dataView, byteOffset, numberOfComponents, componentTypeByteLength, components);
- for (var j = 0; j < numberOfComponents; j++) {
- var value = components[j];
- min[j] = Math.min(min[j], value);
- max[j] = Math.max(max[j], value);
- }
- byteOffset += byteStride;
+ for (var i = 0; i < count; i++) {
+ componentReader(dataView, byteOffset, numberOfComponents, componentTypeByteLength, components);
+ for (var j = 0; j < numberOfComponents; j++) {
+ var value = components[j];
+ min[j] = Math.min(min[j], value);
+ max[j] = Math.max(max[j], value);
}
-
- return {
- min: min,
- max: max
- };
+ byteOffset += byteStride;
}
- export default findAccessorMinMax;
+ return {
+ min: min,
+ max: max
+ };
+}
+
+export default findAccessorMinMax;
diff --git a/Source/ThirdParty/GltfPipeline/forEachTextureInMaterial.js b/Source/ThirdParty/GltfPipeline/forEachTextureInMaterial.js
new file mode 100644
index 000000000000..3e9bcc775eaf
--- /dev/null
+++ b/Source/ThirdParty/GltfPipeline/forEachTextureInMaterial.js
@@ -0,0 +1,134 @@
+import ForEach from "./ForEach.js"
+import Check from "../../Core/Check.js"
+import defined from "../../Core/defined.js"
+
+/**
+ * Calls the provider handler function on each texture used by the material.
+ * Mimics the behavior of functions in gltf-pipeline ForEach.
+ * @param {Object} material The glTF material.
+ * @param {forEachTextureInMaterial~handler} handler Function that is called for each texture in the material.
+ */
+function forEachTextureInMaterial(material, handler) {
+ Check.typeOf.object('material', material);
+ Check.defined('handler', handler);
+
+ // Metallic roughness
+ var pbrMetallicRoughness = material.pbrMetallicRoughness;
+ if (defined(pbrMetallicRoughness)) {
+ if (defined(pbrMetallicRoughness.baseColorTexture)) {
+ var textureInfo = pbrMetallicRoughness.baseColorTexture;
+ var value = handler(textureInfo.index, textureInfo);
+ if (defined(value)) {
+ return value;
+ }
+ }
+ if (defined(pbrMetallicRoughness.metallicRoughnessTexture)) {
+ var textureInfo = pbrMetallicRoughness.metallicRoughnessTexture;
+ var value = handler(textureInfo.index, textureInfo);
+ if (defined(value)) {
+ return value;
+ }
+ }
+ }
+
+ if (defined(material.extensions)) {
+ // Spec gloss extension
+ var pbrSpecularGlossiness = material.extensions.KHR_materials_pbrSpecularGlossiness;
+ if (defined(pbrSpecularGlossiness)) {
+ if (defined(pbrSpecularGlossiness.diffuseTexture)) {
+ var textureInfo = pbrSpecularGlossiness.diffuseTexture;
+ var value = handler(textureInfo.index, textureInfo);
+ if (defined(value)) {
+ return value;
+ }
+ }
+ if (defined(pbrSpecularGlossiness.specularGlossinessTexture)) {
+ var textureInfo = pbrSpecularGlossiness.specularGlossinessTexture;
+ var value = handler(textureInfo.index, textureInfo);
+ if (defined(value)) {
+ return value;
+ }
+ }
+ }
+
+ // Materials common extension (may be present in models converted from glTF 1.0)
+ var materialsCommon = material.extensions.KHR_materials_common;
+ if (defined(materialsCommon)) {
+ var diffuse = materialsCommon.values.diffuse;
+ var ambient = materialsCommon.values.ambient;
+ var emission = materialsCommon.values.emission;
+ var specular = materialsCommon.values.specular;
+ if (defined(diffuse) && defined(diffuse.index)) {
+ var value = handler(diffuse.index, diffuse);
+ if (defined(value)) {
+ return value;
+ }
+ }
+ if (defined(ambient) && defined(ambient.index)) {
+ var value = handler(ambient.index, ambient);
+ if (defined(value)) {
+ return value;
+ }
+ }
+ if (defined(emission) && defined(emission.index)) {
+ var value = handler(emission.index, emission);
+ if (defined(value)) {
+ return value;
+ }
+ }
+ if (defined(specular) && defined(specular.index)) {
+ var value = handler(specular.index, specular);
+ if (defined(value)) {
+ return value;
+ }
+ }
+ }
+ }
+
+ // KHR_techniques_webgl extension
+ var value = ForEach.materialValue(material, function (materialValue) {
+ if (defined(materialValue.index)) {
+ var value = handler(materialValue.index, materialValue);
+ if (defined(value)) {
+ return value;
+ }
+ }
+ });
+ if (defined(value)) {
+ return value;
+ }
+
+ // Top level textures
+ if (defined(material.emissiveTexture)) {
+ var textureInfo = material.emissiveTexture;
+ var value = handler(textureInfo.index, textureInfo);
+ if (defined(value)) {
+ return value;
+ }
+ }
+
+ if (defined(material.normalTexture)) {
+ var textureInfo = material.normalTexture;
+ var value = handler(textureInfo.index, textureInfo);
+ if (defined(value)) {
+ return value;
+ }
+ }
+
+ if (defined(material.occlusionTexture)) {
+ var textureInfo = material.occlusionTexture;
+ var value = handler(textureInfo.index, textureInfo);
+ if (defined(value)) {
+ return value;
+ }
+ }
+}
+
+/**
+ * Function that is called for each texture in the material. If this function returns a value the for each stops and returns that value.
+ * @callback forEachTextureInMaterial~handler
+ * @param {Number} The texture index.
+ * @param {Object} The texture info object.
+ */
+
+export default forEachTextureInMaterial;
diff --git a/Source/ThirdParty/GltfPipeline/getAccessorByteStride.js b/Source/ThirdParty/GltfPipeline/getAccessorByteStride.js
index c0bbecb2249a..a6923e32dffe 100644
--- a/Source/ThirdParty/GltfPipeline/getAccessorByteStride.js
+++ b/Source/ThirdParty/GltfPipeline/getAccessorByteStride.js
@@ -1,26 +1,26 @@
-import numberOfComponentsForType from './numberOfComponentsForType.js'
-import ComponentDatatype from '../../Core/ComponentDatatype.js'
-import defined from '../../Core/defined.js'
+import numberOfComponentsForType from "./numberOfComponentsForType.js"
+import ComponentDatatype from "../../Core/ComponentDatatype.js"
+import defined from "../../Core/defined.js"
- /**
- * Returns the byte stride of the provided accessor.
- * If the byteStride is 0, it is calculated based on type and componentType
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @param {Object} accessor The accessor.
- * @returns {Number} The byte stride of the accessor.
- *
- * @private
- */
- function getAccessorByteStride(gltf, accessor) {
- var bufferViewId = accessor.bufferView;
- if (defined(bufferViewId)) {
- var bufferView = gltf.bufferViews[bufferViewId];
- if (defined(bufferView.byteStride) && bufferView.byteStride > 0) {
- return bufferView.byteStride;
- }
+/**
+ * Returns the byte stride of the provided accessor.
+ * If the byteStride is 0, it is calculated based on type and componentType
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @param {Object} accessor The accessor.
+ * @returns {Number} The byte stride of the accessor.
+ *
+ * @private
+ */
+function getAccessorByteStride(gltf, accessor) {
+ var bufferViewId = accessor.bufferView;
+ if (defined(bufferViewId)) {
+ var bufferView = gltf.bufferViews[bufferViewId];
+ if (defined(bufferView.byteStride) && bufferView.byteStride > 0) {
+ return bufferView.byteStride;
}
- return ComponentDatatype.getSizeInBytes(accessor.componentType) * numberOfComponentsForType(accessor.type);
}
+ return ComponentDatatype.getSizeInBytes(accessor.componentType) * numberOfComponentsForType(accessor.type);
+}
- export default getAccessorByteStride;
+export default getAccessorByteStride;
diff --git a/Source/ThirdParty/GltfPipeline/getComponentReader.js b/Source/ThirdParty/GltfPipeline/getComponentReader.js
index ff406b46d391..c7ad4d9edca6 100644
--- a/Source/ThirdParty/GltfPipeline/getComponentReader.js
+++ b/Source/ThirdParty/GltfPipeline/getComponentReader.js
@@ -1,75 +1,75 @@
-import ComponentDatatype from '../../Core/ComponentDatatype.js'
+import ComponentDatatype from "../../Core/ComponentDatatype.js"
- /**
- * Returns a function to read and convert data from a DataView into an array.
- *
- * @param {Number} componentType Type to convert the data to.
- * @returns {ComponentReader} Function that reads and converts data.
- *
- * @private
- */
- function getComponentReader(componentType) {
- switch (componentType) {
- case ComponentDatatype.BYTE:
- return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
- for (var i = 0; i < numberOfComponents; ++i) {
- result[i] = dataView.getInt8(byteOffset + i * componentTypeByteLength);
- }
- };
- case ComponentDatatype.UNSIGNED_BYTE:
- return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
- for (var i = 0; i < numberOfComponents; ++i) {
- result[i] = dataView.getUint8(byteOffset + i * componentTypeByteLength);
- }
- };
- case ComponentDatatype.SHORT:
- return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
- for (var i = 0; i < numberOfComponents; ++i) {
- result[i] = dataView.getInt16(byteOffset + i * componentTypeByteLength, true);
- }
- };
- case ComponentDatatype.UNSIGNED_SHORT:
- return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
- for (var i = 0; i < numberOfComponents; ++i) {
- result[i] = dataView.getUint16(byteOffset + i * componentTypeByteLength, true);
- }
- };
- case ComponentDatatype.INT:
- return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
- for (var i = 0; i < numberOfComponents; ++i) {
- result[i] = dataView.getInt32(byteOffset + i * componentTypeByteLength, true);
- }
- };
- case ComponentDatatype.UNSIGNED_INT:
- return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
- for (var i = 0; i < numberOfComponents; ++i) {
- result[i] = dataView.getUint32(byteOffset + i * componentTypeByteLength, true);
- }
- };
- case ComponentDatatype.FLOAT:
- return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
- for (var i = 0; i < numberOfComponents; ++i) {
- result[i] = dataView.getFloat32(byteOffset + i * componentTypeByteLength, true);
- }
- };
- case ComponentDatatype.DOUBLE:
- return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
- for (var i = 0; i < numberOfComponents; ++i) {
- result[i] = dataView.getFloat64(byteOffset + i * componentTypeByteLength, true);
- }
- };
- }
+/**
+ * Returns a function to read and convert data from a DataView into an array.
+ *
+ * @param {Number} componentType Type to convert the data to.
+ * @returns {ComponentReader} Function that reads and converts data.
+ *
+ * @private
+ */
+function getComponentReader(componentType) {
+ switch (componentType) {
+ case ComponentDatatype.BYTE:
+ return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
+ for (var i = 0; i < numberOfComponents; ++i) {
+ result[i] = dataView.getInt8(byteOffset + i * componentTypeByteLength);
+ }
+ };
+ case ComponentDatatype.UNSIGNED_BYTE:
+ return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
+ for (var i = 0; i < numberOfComponents; ++i) {
+ result[i] = dataView.getUint8(byteOffset + i * componentTypeByteLength);
+ }
+ };
+ case ComponentDatatype.SHORT:
+ return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
+ for (var i = 0; i < numberOfComponents; ++i) {
+ result[i] = dataView.getInt16(byteOffset + i * componentTypeByteLength, true);
+ }
+ };
+ case ComponentDatatype.UNSIGNED_SHORT:
+ return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
+ for (var i = 0; i < numberOfComponents; ++i) {
+ result[i] = dataView.getUint16(byteOffset + i * componentTypeByteLength, true);
+ }
+ };
+ case ComponentDatatype.INT:
+ return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
+ for (var i = 0; i < numberOfComponents; ++i) {
+ result[i] = dataView.getInt32(byteOffset + i * componentTypeByteLength, true);
+ }
+ };
+ case ComponentDatatype.UNSIGNED_INT:
+ return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
+ for (var i = 0; i < numberOfComponents; ++i) {
+ result[i] = dataView.getUint32(byteOffset + i * componentTypeByteLength, true);
+ }
+ };
+ case ComponentDatatype.FLOAT:
+ return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
+ for (var i = 0; i < numberOfComponents; ++i) {
+ result[i] = dataView.getFloat32(byteOffset + i * componentTypeByteLength, true);
+ }
+ };
+ case ComponentDatatype.DOUBLE:
+ return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {
+ for (var i = 0; i < numberOfComponents; ++i) {
+ result[i] = dataView.getFloat64(byteOffset + i * componentTypeByteLength, true);
+ }
+ };
}
+}
- /**
- * A callback function that logs messages.
- * @callback ComponentReader
- *
- * @param {DataView} dataView The data view to read from.
- * @param {Number} byteOffset The byte offset applied when reading from the data view.
- * @param {Number} numberOfComponents The number of components to read.
- * @param {Number} componentTypeByteLength The byte length of each component.
- * @param {Number} result An array storing the components that are read.
- */
+/**
+ * A callback function that logs messages.
+ * @callback ComponentReader
+ *
+ * @param {DataView} dataView The data view to read from.
+ * @param {Number} byteOffset The byte offset applied when reading from the data view.
+ * @param {Number} numberOfComponents The number of components to read.
+ * @param {Number} componentTypeByteLength The byte length of each component.
+ * @param {Number} result An array storing the components that are read.
+ */
- export default getComponentReader;
+export default getComponentReader;
diff --git a/Source/ThirdParty/GltfPipeline/moveTechniqueRenderStates.js b/Source/ThirdParty/GltfPipeline/moveTechniqueRenderStates.js
index c6f9847c9932..24bf5dd6b941 100644
--- a/Source/ThirdParty/GltfPipeline/moveTechniqueRenderStates.js
+++ b/Source/ThirdParty/GltfPipeline/moveTechniqueRenderStates.js
@@ -1,129 +1,129 @@
-import addExtensionsUsed from './addExtensionsUsed.js'
-import ForEach from './ForEach.js'
-import defaultValue from '../../Core/defaultValue.js'
-import defined from '../../Core/defined.js'
-import WebGLConstants from '../../Core/WebGLConstants.js'
-
- var defaultBlendEquation = [
- WebGLConstants.FUNC_ADD,
- WebGLConstants.FUNC_ADD
- ];
-
- var defaultBlendFactors = [
- WebGLConstants.ONE,
- WebGLConstants.ZERO,
- WebGLConstants.ONE,
- WebGLConstants.ZERO
- ];
-
- function isStateEnabled(renderStates, state) {
- var enabled = renderStates.enable;
- if (!defined(enabled)) {
- return false;
- }
+import addExtensionsUsed from "./addExtensionsUsed.js"
+import ForEach from "./ForEach.js"
+import defaultValue from "../../Core/defaultValue.js"
+import defined from "../../Core/defined.js"
+import WebGLConstants from "../../Core/WebGLConstants.js"
+
+var defaultBlendEquation = [
+ WebGLConstants.FUNC_ADD,
+ WebGLConstants.FUNC_ADD
+];
+
+var defaultBlendFactors = [
+ WebGLConstants.ONE,
+ WebGLConstants.ZERO,
+ WebGLConstants.ONE,
+ WebGLConstants.ZERO
+];
+
+function isStateEnabled(renderStates, state) {
+ var enabled = renderStates.enable;
+ if (!defined(enabled)) {
+ return false;
+ }
- return (enabled.indexOf(state) > -1);
+ return (enabled.indexOf(state) > -1);
+}
+
+var supportedBlendFactors = [
+ WebGLConstants.ZERO,
+ WebGLConstants.ONE,
+ WebGLConstants.SRC_COLOR,
+ WebGLConstants.ONE_MINUS_SRC_COLOR,
+ WebGLConstants.SRC_ALPHA,
+ WebGLConstants.ONE_MINUS_SRC_ALPHA,
+ WebGLConstants.DST_ALPHA,
+ WebGLConstants.ONE_MINUS_DST_ALPHA,
+ WebGLConstants.DST_COLOR,
+ WebGLConstants.ONE_MINUS_DST_COLOR
+];
+
+// If any of the blend factors are not supported, return the default
+function getSupportedBlendFactors(value, defaultValue) {
+ if (!defined(value)) {
+ return defaultValue;
}
- var supportedBlendFactors = [
- WebGLConstants.ZERO,
- WebGLConstants.ONE,
- WebGLConstants.SRC_COLOR,
- WebGLConstants.ONE_MINUS_SRC_COLOR,
- WebGLConstants.SRC_ALPHA,
- WebGLConstants.ONE_MINUS_SRC_ALPHA,
- WebGLConstants.DST_ALPHA,
- WebGLConstants.ONE_MINUS_DST_ALPHA,
- WebGLConstants.DST_COLOR,
- WebGLConstants.ONE_MINUS_DST_COLOR
- ];
-
- // If any of the blend factors are not supported, return the default
- function getSupportedBlendFactors(value, defaultValue) {
- if (!defined(value)) {
+ for (var i = 0; i < 4; i++) {
+ if (supportedBlendFactors.indexOf(value[i]) === -1) {
return defaultValue;
}
-
- for (var i = 0; i < 4; i++) {
- if (supportedBlendFactors.indexOf(value[i]) === -1) {
- return defaultValue;
- }
- }
-
- return value;
}
- /**
- * Move glTF 1.0 technique render states to glTF 2.0 materials properties and KHR_blend extension.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @returns {Object} The updated glTF asset.
- *
- * @private
- */
- function moveTechniqueRenderStates(gltf) {
- var blendingForTechnique = {};
- var materialPropertiesForTechnique = {};
- var techniquesLegacy = gltf.techniques;
- if (!defined(techniquesLegacy)) {
- return gltf;
- }
-
- ForEach.technique(gltf, function (techniqueLegacy, techniqueIndex) {
- var renderStates = techniqueLegacy.states;
- if (defined(renderStates)) {
- var materialProperties = materialPropertiesForTechnique[techniqueIndex] = {};
-
- // If BLEND is enabled, the material should have alpha mode BLEND
- if (isStateEnabled(renderStates, WebGLConstants.BLEND)) {
- materialProperties.alphaMode = 'BLEND';
-
- var blendFunctions = renderStates.functions;
- if (defined(blendFunctions) && (defined(blendFunctions.blendEquationSeparate)
- || defined(blendFunctions.blendFuncSeparate))) {
- blendingForTechnique[techniqueIndex] = {
- blendEquation: defaultValue(blendFunctions.blendEquationSeparate, defaultBlendEquation),
- blendFactors: getSupportedBlendFactors(blendFunctions.blendFuncSeparate, defaultBlendFactors)
- };
- }
- }
+ return value;
+}
+
+/**
+ * Move glTF 1.0 technique render states to glTF 2.0 materials properties and KHR_blend extension.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @returns {Object} The updated glTF asset.
+ *
+ * @private
+ */
+function moveTechniqueRenderStates(gltf) {
+ var blendingForTechnique = {};
+ var materialPropertiesForTechnique = {};
+ var techniquesLegacy = gltf.techniques;
+ if (!defined(techniquesLegacy)) {
+ return gltf;
+ }
- // If CULL_FACE is not enabled, the material should be doubleSided
- if (!isStateEnabled(renderStates, WebGLConstants.CULL_FACE)) {
- materialProperties.doubleSided = true;
+ ForEach.technique(gltf, function (techniqueLegacy, techniqueIndex) {
+ var renderStates = techniqueLegacy.states;
+ if (defined(renderStates)) {
+ var materialProperties = materialPropertiesForTechnique[techniqueIndex] = {};
+
+ // If BLEND is enabled, the material should have alpha mode BLEND
+ if (isStateEnabled(renderStates, WebGLConstants.BLEND)) {
+ materialProperties.alphaMode = 'BLEND';
+
+ var blendFunctions = renderStates.functions;
+ if (defined(blendFunctions) && (defined(blendFunctions.blendEquationSeparate)
+ || defined(blendFunctions.blendFuncSeparate))) {
+ blendingForTechnique[techniqueIndex] = {
+ blendEquation: defaultValue(blendFunctions.blendEquationSeparate, defaultBlendEquation),
+ blendFactors: getSupportedBlendFactors(blendFunctions.blendFuncSeparate, defaultBlendFactors)
+ };
}
-
- delete techniqueLegacy.states;
}
- });
- if (Object.keys(blendingForTechnique).length > 0) {
- if (!defined(gltf.extensions)) {
- gltf.extensions = {};
+ // If CULL_FACE is not enabled, the material should be doubleSided
+ if (!isStateEnabled(renderStates, WebGLConstants.CULL_FACE)) {
+ materialProperties.doubleSided = true;
}
- addExtensionsUsed(gltf, 'KHR_blend');
+ delete techniqueLegacy.states;
}
+ });
- ForEach.material(gltf, function (material) {
- if (defined(material.technique)) {
- var materialProperties = materialPropertiesForTechnique[material.technique];
- ForEach.objectLegacy(materialProperties, function (value, property) {
- material[property] = value;
- });
+ if (Object.keys(blendingForTechnique).length > 0) {
+ if (!defined(gltf.extensions)) {
+ gltf.extensions = {};
+ }
- var blending = blendingForTechnique[material.technique];
- if (defined(blending)) {
- if (!defined(material.extensions)) {
- material.extensions = {};
- }
+ addExtensionsUsed(gltf, 'KHR_blend');
+ }
- material.extensions.KHR_blend = blending;
+ ForEach.material(gltf, function (material) {
+ if (defined(material.technique)) {
+ var materialProperties = materialPropertiesForTechnique[material.technique];
+ ForEach.objectLegacy(materialProperties, function (value, property) {
+ material[property] = value;
+ });
+
+ var blending = blendingForTechnique[material.technique];
+ if (defined(blending)) {
+ if (!defined(material.extensions)) {
+ material.extensions = {};
}
+
+ material.extensions.KHR_blend = blending;
}
- });
+ }
+ });
- return gltf;
- }
+ return gltf;
+}
- export default moveTechniqueRenderStates;
+export default moveTechniqueRenderStates;
diff --git a/Source/ThirdParty/GltfPipeline/moveTechniquesToExtension.js b/Source/ThirdParty/GltfPipeline/moveTechniquesToExtension.js
index 96c7631a6fc2..f47e57762c0a 100644
--- a/Source/ThirdParty/GltfPipeline/moveTechniquesToExtension.js
+++ b/Source/ThirdParty/GltfPipeline/moveTechniquesToExtension.js
@@ -1,63 +1,69 @@
-import addExtensionsUsed from './addExtensionsUsed.js'
-import addExtensionsRequired from './addExtensionsRequired.js'
-import addToArray from './addToArray.js'
-import ForEach from './ForEach.js'
-import defined from '../../Core/defined.js'
-
- /**
- * Move glTF 1.0 material techniques to glTF 2.0 KHR_techniques_webgl extension.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @returns {Object} The updated glTF asset.
- *
- * @private
- */
- function moveTechniquesToExtension(gltf) {
- var techniquesLegacy = gltf.techniques;
- var mappedUniforms = {};
- var updatedTechniqueIndices = {};
- if (defined(techniquesLegacy)) {
- var extension = {
- programs: [],
- shaders: [],
- techniques: []
+import addExtensionsUsed from "./addExtensionsUsed.js"
+import addExtensionsRequired from "./addExtensionsRequired.js"
+import addToArray from "./addToArray.js"
+import ForEach from "./ForEach.js"
+import defined from "../../Core/defined.js"
+
+/**
+ * Move glTF 1.0 material techniques to glTF 2.0 KHR_techniques_webgl extension.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @returns {Object} The updated glTF asset.
+ *
+ * @private
+ */
+function moveTechniquesToExtension(gltf) {
+ var techniquesLegacy = gltf.techniques;
+ var mappedUniforms = {};
+ var updatedTechniqueIndices = {};
+ var seenPrograms = {};
+ if (defined(techniquesLegacy)) {
+ var extension = {
+ programs: [],
+ shaders: [],
+ techniques: []
+ };
+
+ // Some 1.1 models have a glExtensionsUsed property that can be transferred to program.glExtensions
+ var glExtensions = gltf.glExtensionsUsed;
+ delete gltf.glExtensionsUsed;
+
+ ForEach.technique(gltf, function (techniqueLegacy, techniqueId) {
+ var technique = {
+ name: techniqueLegacy.name,
+ program: undefined,
+ attributes: {},
+ uniforms: {}
};
- // Some 1.1 models have a glExtensionsUsed property that can be transferred to program.glExtensions
- var glExtensions = gltf.glExtensionsUsed;
- delete gltf.glExtensionsUsed;
+ var parameterLegacy;
+ ForEach.techniqueAttribute(techniqueLegacy, function (parameterName, attributeName) {
+ parameterLegacy = techniqueLegacy.parameters[parameterName];
+ technique.attributes[attributeName] = {
+ semantic: parameterLegacy.semantic
+ };
+ });
- ForEach.technique(gltf, function (techniqueLegacy, techniqueIndex) {
- var technique = {
- name: techniqueLegacy.name,
- program: undefined,
- attributes: {},
- uniforms: {}
+ ForEach.techniqueUniform(techniqueLegacy, function (parameterName, uniformName) {
+ parameterLegacy = techniqueLegacy.parameters[parameterName];
+ technique.uniforms[uniformName] = {
+ count: parameterLegacy.count,
+ node: parameterLegacy.node,
+ type: parameterLegacy.type,
+ semantic: parameterLegacy.semantic,
+ value: parameterLegacy.value
};
- var parameterLegacy;
- ForEach.techniqueAttribute(techniqueLegacy, function (parameterName, attributeName) {
- parameterLegacy = techniqueLegacy.parameters[parameterName];
- technique.attributes[attributeName] = {
- semantic: parameterLegacy.semantic
- };
- });
-
- ForEach.techniqueUniform(techniqueLegacy, function (parameterName, uniformName) {
- parameterLegacy = techniqueLegacy.parameters[parameterName];
- technique.uniforms[uniformName] = {
- count: parameterLegacy.count,
- node: parameterLegacy.node,
- type: parameterLegacy.type,
- semantic: parameterLegacy.semantic,
- value: parameterLegacy.value
- };
-
- // Store the name of the uniform to update material values.
- mappedUniforms[parameterName] = uniformName;
- });
+ // Store the name of the uniform to update material values.
+ if (!defined(mappedUniforms[techniqueId])) {
+ mappedUniforms[techniqueId] = {};
+ }
+ mappedUniforms[techniqueId][parameterName] = uniformName;
+ });
+ if (!defined(seenPrograms[techniqueLegacy.program])) {
var programLegacy = gltf.programs[techniqueLegacy.program];
+
var program = {
name: programLegacy.name,
fragmentShader: undefined,
@@ -72,53 +78,57 @@ import defined from '../../Core/defined.js'
program.vertexShader = addToArray(extension.shaders, vs, true);
technique.program = addToArray(extension.programs, program);
+ seenPrograms[techniqueLegacy.program] = technique.program;
+ } else {
+ technique.program = seenPrograms[techniqueLegacy.program];
+ }
- // Store the index of the new technique to reference instead.
- updatedTechniqueIndices[techniqueIndex] = addToArray(extension.techniques, technique);
- });
-
- if (extension.techniques.length > 0) {
- if (!defined(gltf.extensions)) {
- gltf.extensions = {};
- }
+ // Store the index of the new technique to reference instead.
+ updatedTechniqueIndices[techniqueId] = addToArray(extension.techniques, technique);
+ });
- gltf.extensions.KHR_techniques_webgl = extension;
- addExtensionsUsed(gltf, 'KHR_techniques_webgl');
- addExtensionsRequired(gltf, 'KHR_techniques_webgl');
+ if (extension.techniques.length > 0) {
+ if (!defined(gltf.extensions)) {
+ gltf.extensions = {};
}
- }
- ForEach.material(gltf, function (material) {
- if (defined(material.technique)) {
- var materialExtension = {
- technique: updatedTechniqueIndices[material.technique]
- };
-
- ForEach.objectLegacy(material.values, function (value, parameterName) {
- if (!defined(materialExtension.values)) {
- materialExtension.values = {};
- }
+ gltf.extensions.KHR_techniques_webgl = extension;
+ addExtensionsUsed(gltf, 'KHR_techniques_webgl');
+ addExtensionsRequired(gltf, 'KHR_techniques_webgl');
+ }
+ }
- var uniformName = mappedUniforms[parameterName];
- materialExtension.values[uniformName] = value;
- });
+ ForEach.material(gltf, function (material) {
+ if (defined(material.technique)) {
+ var materialExtension = {
+ technique: updatedTechniqueIndices[material.technique]
+ };
- if (!defined(material.extensions)) {
- material.extensions = {};
+ ForEach.objectLegacy(material.values, function (value, parameterName) {
+ if (!defined(materialExtension.values)) {
+ materialExtension.values = {};
}
- material.extensions.KHR_techniques_webgl = materialExtension;
+ var uniformName = mappedUniforms[material.technique][parameterName];
+ materialExtension.values[uniformName] = value;
+ });
+
+ if (!defined(material.extensions)) {
+ material.extensions = {};
}
- delete material.technique;
- delete material.values;
- });
+ material.extensions.KHR_techniques_webgl = materialExtension;
+ }
- delete gltf.techniques;
- delete gltf.programs;
- delete gltf.shaders;
+ delete material.technique;
+ delete material.values;
+ });
- return gltf;
- }
+ delete gltf.techniques;
+ delete gltf.programs;
+ delete gltf.shaders;
+
+ return gltf;
+}
- export default moveTechniquesToExtension;
+export default moveTechniquesToExtension;
diff --git a/Source/ThirdParty/GltfPipeline/numberOfComponentsForType.js b/Source/ThirdParty/GltfPipeline/numberOfComponentsForType.js
index 36af8038a64b..d211357f0634 100644
--- a/Source/ThirdParty/GltfPipeline/numberOfComponentsForType.js
+++ b/Source/ThirdParty/GltfPipeline/numberOfComponentsForType.js
@@ -1,29 +1,29 @@
- /**
- * Utility function for retrieving the number of components in a given type.
- *
- * @param {String} type glTF type
- * @returns {Number} The number of components in that type.
- *
- * @private
- */
- function numberOfComponentsForType(type) {
- switch (type) {
- case 'SCALAR':
- return 1;
- case 'VEC2':
- return 2;
- case 'VEC3':
- return 3;
- case 'VEC4':
- case 'MAT2':
- return 4;
- case 'MAT3':
- return 9;
- case 'MAT4':
- return 16;
- }
+/**
+ * Utility function for retrieving the number of components in a given type.
+ *
+ * @param {String} type glTF type
+ * @returns {Number} The number of components in that type.
+ *
+ * @private
+ */
+function numberOfComponentsForType(type) {
+ switch (type) {
+ case 'SCALAR':
+ return 1;
+ case 'VEC2':
+ return 2;
+ case 'VEC3':
+ return 3;
+ case 'VEC4':
+ case 'MAT2':
+ return 4;
+ case 'MAT3':
+ return 9;
+ case 'MAT4':
+ return 16;
}
+}
- export default numberOfComponentsForType;
+export default numberOfComponentsForType;
diff --git a/Source/ThirdParty/GltfPipeline/parseGlb.js b/Source/ThirdParty/GltfPipeline/parseGlb.js
index e1460864700a..0acfd28f6a12 100644
--- a/Source/ThirdParty/GltfPipeline/parseGlb.js
+++ b/Source/ThirdParty/GltfPipeline/parseGlb.js
@@ -1,114 +1,116 @@
-import addPipelineExtras from './addPipelineExtras.js'
-import removeExtensionsUsed from './removeExtensionsUsed.js'
-import defaultValue from '../../Core/defaultValue.js'
-import defined from '../../Core/defined.js'
-import getJsonFromTypedArray from '../../Core/getJsonFromTypedArray.js'
-import getMagic from '../../Core/getMagic.js'
-import RuntimeError from '../../Core/RuntimeError.js'
+import addPipelineExtras from "./addPipelineExtras.js"
+import removeExtensionsUsed from "./removeExtensionsUsed.js"
+import defaultValue from "../../Core/defaultValue.js"
+import defined from "../../Core/defined.js"
+import getMagic from "../../Core/getMagic.js"
+import getStringFromTypedArray from "../../Core/getStringFromTypedArray.js"
+import RuntimeError from "../../Core/RuntimeError.js"
- var sizeOfUint32 = 4;
+var sizeOfUint32 = 4;
- /**
- * Convert a binary glTF to glTF.
- *
- * The returned glTF has pipeline extras included. The embedded binary data is stored in gltf.buffers[0].extras._pipeline.source.
- *
- * @param {Buffer} glb The glb data to parse.
- * @returns {Object} A javascript object containing a glTF asset with pipeline extras included.
- *
- * @private
- */
- function parseGlb(glb) {
- // Check that the magic string is present
- var magic = getMagic(glb);
- if (magic !== 'glTF') {
- throw new RuntimeError('File is not valid binary glTF');
- }
-
- var header = readHeader(glb, 0, 5);
- var version = header[1];
- if (version !== 1 && version !== 2) {
- throw new RuntimeError('Binary glTF version is not 1 or 2');
- }
+/**
+ * Convert a binary glTF to glTF.
+ *
+ * The returned glTF has pipeline extras included. The embedded binary data is stored in gltf.buffers[0].extras._pipeline.source.
+ *
+ * @param {Buffer} glb The glb data to parse.
+ * @returns {Object} A javascript object containing a glTF asset with pipeline extras included.
+ *
+ * @private
+ */
+function parseGlb(glb) {
+ // Check that the magic string is present
+ var magic = getMagic(glb);
+ if (magic !== 'glTF') {
+ throw new RuntimeError('File is not valid binary glTF');
+ }
- if (version === 1) {
- return parseGlbVersion1(glb, header);
- }
+ var header = readHeader(glb, 0, 5);
+ var version = header[1];
+ if (version !== 1 && version !== 2) {
+ throw new RuntimeError('Binary glTF version is not 1 or 2');
+ }
- return parseGlbVersion2(glb, header);
+ if (version === 1) {
+ return parseGlbVersion1(glb, header);
}
- function readHeader(glb, byteOffset, count) {
- var dataView = new DataView(glb.buffer);
- var header = new Array(count);
- for (var i = 0; i < count; ++i) {
- header[i] = dataView.getUint32(glb.byteOffset + byteOffset + i * sizeOfUint32, true);
- }
- return header;
+ return parseGlbVersion2(glb, header);
+}
+
+function readHeader(glb, byteOffset, count) {
+ var dataView = new DataView(glb.buffer);
+ var header = new Array(count);
+ for (var i = 0; i < count; ++i) {
+ header[i] = dataView.getUint32(glb.byteOffset + byteOffset + i * sizeOfUint32, true);
}
+ return header;
+}
- function parseGlbVersion1(glb, header) {
- var length = header[2];
- var contentLength = header[3];
- var contentFormat = header[4];
+function parseGlbVersion1(glb, header) {
+ var length = header[2];
+ var contentLength = header[3];
+ var contentFormat = header[4];
- // Check that the content format is 0, indicating that it is JSON
- if (contentFormat !== 0) {
- throw new RuntimeError('Binary glTF scene format is not JSON');
- }
+ // Check that the content format is 0, indicating that it is JSON
+ if (contentFormat !== 0) {
+ throw new RuntimeError('Binary glTF scene format is not JSON');
+ }
- var jsonStart = 20;
- var binaryStart = jsonStart + contentLength;
+ var jsonStart = 20;
+ var binaryStart = jsonStart + contentLength;
- var gltf = getJsonFromTypedArray(glb, jsonStart, contentLength);
- addPipelineExtras(gltf);
+ var contentString = getStringFromTypedArray(glb, jsonStart, contentLength);
+ var gltf = JSON.parse(contentString);
+ addPipelineExtras(gltf);
- var binaryBuffer = glb.subarray(binaryStart, length);
+ var binaryBuffer = glb.subarray(binaryStart, length);
- var buffers = gltf.buffers;
- if (defined(buffers) && Object.keys(buffers).length > 0) {
- // In some older models, the binary glTF buffer is named KHR_binary_glTF
- var binaryGltfBuffer = defaultValue(buffers.binary_glTF, buffers.KHR_binary_glTF);
- if (defined(binaryGltfBuffer)) {
- binaryGltfBuffer.extras._pipeline.source = binaryBuffer;
- delete binaryGltfBuffer.uri;
- }
+ var buffers = gltf.buffers;
+ if (defined(buffers) && Object.keys(buffers).length > 0) {
+ // In some older models, the binary glTF buffer is named KHR_binary_glTF
+ var binaryGltfBuffer = defaultValue(buffers.binary_glTF, buffers.KHR_binary_glTF);
+ if (defined(binaryGltfBuffer)) {
+ binaryGltfBuffer.extras._pipeline.source = binaryBuffer;
+ delete binaryGltfBuffer.uri;
}
- // Remove the KHR_binary_glTF extension
- removeExtensionsUsed(gltf, 'KHR_binary_glTF');
- return gltf;
}
+ // Remove the KHR_binary_glTF extension
+ removeExtensionsUsed(gltf, 'KHR_binary_glTF');
+ return gltf;
+}
- function parseGlbVersion2(glb, header) {
- var length = header[2];
- var byteOffset = 12;
- var gltf;
- var binaryBuffer;
- while (byteOffset < length) {
- var chunkHeader = readHeader(glb, byteOffset, 2);
- var chunkLength = chunkHeader[0];
- var chunkType = chunkHeader[1];
- byteOffset += 8;
- var chunkBuffer = glb.subarray(byteOffset, byteOffset + chunkLength);
- byteOffset += chunkLength;
- // Load JSON chunk
- if (chunkType === 0x4E4F534A) {
- gltf = getJsonFromTypedArray(chunkBuffer);
- addPipelineExtras(gltf);
- }
- // Load Binary chunk
- else if (chunkType === 0x004E4942) {
- binaryBuffer = chunkBuffer;
- }
+function parseGlbVersion2(glb, header) {
+ var length = header[2];
+ var byteOffset = 12;
+ var gltf;
+ var binaryBuffer;
+ while (byteOffset < length) {
+ var chunkHeader = readHeader(glb, byteOffset, 2);
+ var chunkLength = chunkHeader[0];
+ var chunkType = chunkHeader[1];
+ byteOffset += 8;
+ var chunkBuffer = glb.subarray(byteOffset, byteOffset + chunkLength);
+ byteOffset += chunkLength;
+ // Load JSON chunk
+ if (chunkType === 0x4E4F534A) {
+ var jsonString = getStringFromTypedArray(chunkBuffer);
+ gltf = JSON.parse(jsonString);
+ addPipelineExtras(gltf);
}
- if (defined(gltf) && defined(binaryBuffer)) {
- var buffers = gltf.buffers;
- if (defined(buffers) && buffers.length > 0) {
- var buffer = buffers[0];
- buffer.extras._pipeline.source = binaryBuffer;
- }
+ // Load Binary chunk
+ else if (chunkType === 0x004E4942) {
+ binaryBuffer = chunkBuffer;
+ }
+ }
+ if (defined(gltf) && defined(binaryBuffer)) {
+ var buffers = gltf.buffers;
+ if (defined(buffers) && buffers.length > 0) {
+ var buffer = buffers[0];
+ buffer.extras._pipeline.source = binaryBuffer;
}
- return gltf;
}
+ return gltf;
+}
- export default parseGlb;
+export default parseGlb;
diff --git a/Source/ThirdParty/GltfPipeline/readAccessorPacked.js b/Source/ThirdParty/GltfPipeline/readAccessorPacked.js
index 6225e4f545be..0efb0217b93d 100644
--- a/Source/ThirdParty/GltfPipeline/readAccessorPacked.js
+++ b/Source/ThirdParty/GltfPipeline/readAccessorPacked.js
@@ -1,47 +1,47 @@
-import getAccessorByteStride from './getAccessorByteStride.js'
-import getComponentReader from './getComponentReader.js'
-import numberOfComponentsForType from './numberOfComponentsForType.js'
-import arrayFill from '../../Core/arrayFill.js'
-import ComponentDatatype from '../../Core/ComponentDatatype.js'
-import defined from '../../Core/defined.js'
+import getAccessorByteStride from "./getAccessorByteStride.js"
+import getComponentReader from "./getComponentReader.js"
+import numberOfComponentsForType from "./numberOfComponentsForType.js"
+import arrayFill from "../../Core/arrayFill.js"
+import ComponentDatatype from "../../Core/ComponentDatatype.js"
+import defined from "../../Core/defined.js"
- /**
- * Returns the accessor data in a contiguous array.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @param {Object} accessor The accessor.
- * @returns {Array} The accessor values in a contiguous array.
- *
- * @private
- */
- function readAccessorPacked(gltf, accessor) {
- var byteStride = getAccessorByteStride(gltf, accessor);
- var componentTypeByteLength = ComponentDatatype.getSizeInBytes(accessor.componentType);
- var numberOfComponents = numberOfComponentsForType(accessor.type);
- var count = accessor.count;
- var values = new Array(numberOfComponents * count);
+/**
+ * Returns the accessor data in a contiguous array.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @param {Object} accessor The accessor.
+ * @returns {Array} The accessor values in a contiguous array.
+ *
+ * @private
+ */
+function readAccessorPacked(gltf, accessor) {
+ var byteStride = getAccessorByteStride(gltf, accessor);
+ var componentTypeByteLength = ComponentDatatype.getSizeInBytes(accessor.componentType);
+ var numberOfComponents = numberOfComponentsForType(accessor.type);
+ var count = accessor.count;
+ var values = new Array(numberOfComponents * count);
- if (!defined(accessor.bufferView)) {
- arrayFill(values, 0);
- return values;
- }
+ if (!defined(accessor.bufferView)) {
+ arrayFill(values, 0);
+ return values;
+ }
- var bufferView = gltf.bufferViews[accessor.bufferView];
- var source = gltf.buffers[bufferView.buffer].extras._pipeline.source;
- var byteOffset = accessor.byteOffset + bufferView.byteOffset + source.byteOffset;
+ var bufferView = gltf.bufferViews[accessor.bufferView];
+ var source = gltf.buffers[bufferView.buffer].extras._pipeline.source;
+ var byteOffset = accessor.byteOffset + bufferView.byteOffset + source.byteOffset;
- var dataView = new DataView(source.buffer);
- var components = new Array(numberOfComponents);
- var componentReader = getComponentReader(accessor.componentType);
+ var dataView = new DataView(source.buffer);
+ var components = new Array(numberOfComponents);
+ var componentReader = getComponentReader(accessor.componentType);
- for (var i = 0; i < count; ++i) {
- componentReader(dataView, byteOffset, numberOfComponents, componentTypeByteLength, components);
- for (var j = 0; j < numberOfComponents; ++j) {
- values[i * numberOfComponents + j] = components[j];
- }
- byteOffset += byteStride;
+ for (var i = 0; i < count; ++i) {
+ componentReader(dataView, byteOffset, numberOfComponents, componentTypeByteLength, components);
+ for (var j = 0; j < numberOfComponents; ++j) {
+ values[i * numberOfComponents + j] = components[j];
}
- return values;
+ byteOffset += byteStride;
}
+ return values;
+}
- export default readAccessorPacked;
+export default readAccessorPacked;
diff --git a/Source/ThirdParty/GltfPipeline/removeExtensionsRequired.js b/Source/ThirdParty/GltfPipeline/removeExtensionsRequired.js
index ba60c8211525..44fb89ddfd5e 100644
--- a/Source/ThirdParty/GltfPipeline/removeExtensionsRequired.js
+++ b/Source/ThirdParty/GltfPipeline/removeExtensionsRequired.js
@@ -1,24 +1,24 @@
-import defined from '../../Core/defined.js'
+import defined from "../../Core/defined.js"
- /**
- * Removes an extension from gltf.extensionsRequired if it is present.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @param {String} extension The extension to remove.
- *
- * @private
- */
- function removeExtensionsRequired(gltf, extension) {
- var extensionsRequired = gltf.extensionsRequired;
- if (defined(extensionsRequired)) {
- var index = extensionsRequired.indexOf(extension);
- if (index >= 0) {
- extensionsRequired.splice(index, 1);
- }
- if (extensionsRequired.length === 0) {
- delete gltf.extensionsRequired;
- }
+/**
+ * Removes an extension from gltf.extensionsRequired if it is present.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @param {String} extension The extension to remove.
+ *
+ * @private
+ */
+function removeExtensionsRequired(gltf, extension) {
+ var extensionsRequired = gltf.extensionsRequired;
+ if (defined(extensionsRequired)) {
+ var index = extensionsRequired.indexOf(extension);
+ if (index >= 0) {
+ extensionsRequired.splice(index, 1);
+ }
+ if (extensionsRequired.length === 0) {
+ delete gltf.extensionsRequired;
}
}
+}
- export default removeExtensionsRequired;
+export default removeExtensionsRequired;
diff --git a/Source/ThirdParty/GltfPipeline/removeExtensionsUsed.js b/Source/ThirdParty/GltfPipeline/removeExtensionsUsed.js
index 83f8aad1ee38..28d199c18a55 100644
--- a/Source/ThirdParty/GltfPipeline/removeExtensionsUsed.js
+++ b/Source/ThirdParty/GltfPipeline/removeExtensionsUsed.js
@@ -1,26 +1,26 @@
-import removeExtensionsRequired from './removeExtensionsRequired.js'
-import defined from '../../Core/defined.js'
+import removeExtensionsRequired from "./removeExtensionsRequired.js"
+import defined from "../../Core/defined.js"
- /**
- * Removes an extension from gltf.extensionsUsed and gltf.extensionsRequired if it is present.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @param {String} extension The extension to remove.
- *
- * @private
- */
- function removeExtensionsUsed(gltf, extension) {
- var extensionsUsed = gltf.extensionsUsed;
- if (defined(extensionsUsed)) {
- var index = extensionsUsed.indexOf(extension);
- if (index >= 0) {
- extensionsUsed.splice(index, 1);
- }
- removeExtensionsRequired(gltf, extension);
- if (extensionsUsed.length === 0) {
- delete gltf.extensionsUsed;
- }
+/**
+ * Removes an extension from gltf.extensionsUsed and gltf.extensionsRequired if it is present.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @param {String} extension The extension to remove.
+ *
+ * @private
+ */
+function removeExtensionsUsed(gltf, extension) {
+ var extensionsUsed = gltf.extensionsUsed;
+ if (defined(extensionsUsed)) {
+ var index = extensionsUsed.indexOf(extension);
+ if (index >= 0) {
+ extensionsUsed.splice(index, 1);
+ }
+ removeExtensionsRequired(gltf, extension);
+ if (extensionsUsed.length === 0) {
+ delete gltf.extensionsUsed;
}
}
+}
- export default removeExtensionsUsed;
+export default removeExtensionsUsed;
diff --git a/Source/ThirdParty/GltfPipeline/removePipelineExtras.js b/Source/ThirdParty/GltfPipeline/removePipelineExtras.js
index 25fcbf760e81..5e5cdcac2fec 100644
--- a/Source/ThirdParty/GltfPipeline/removePipelineExtras.js
+++ b/Source/ThirdParty/GltfPipeline/removePipelineExtras.js
@@ -1,45 +1,42 @@
-import ForEach from './ForEach.js'
-import defined from '../../Core/defined.js'
+import ForEach from "./ForEach.js"
+import defined from "../../Core/defined.js"
- /**
- * Iterate through the objects within the glTF and delete their pipeline extras object.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @returns {Object} glTF with no pipeline extras.
- *
- * @private
- */
- function removePipelineExtras(gltf) {
- ForEach.shader(gltf, function(shader) {
- removeExtras(shader);
- });
- ForEach.buffer(gltf, function(buffer) {
- removeExtras(buffer);
- });
- ForEach.image(gltf, function (image) {
- removeExtras(image);
- ForEach.compressedImage(image, function(compressedImage) {
- removeExtras(compressedImage);
- });
- });
+/**
+ * Iterate through the objects within the glTF and delete their pipeline extras object.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @returns {Object} glTF with no pipeline extras.
+ *
+ * @private
+ */
+function removePipelineExtras(gltf) {
+ ForEach.shader(gltf, function(shader) {
+ removeExtras(shader);
+ });
+ ForEach.buffer(gltf, function(buffer) {
+ removeExtras(buffer);
+ });
+ ForEach.image(gltf, function (image) {
+ removeExtras(image);
+ });
- removeExtras(gltf);
+ removeExtras(gltf);
- return gltf;
- }
+ return gltf;
+}
- function removeExtras(object) {
- if (!defined(object.extras)) {
- return;
- }
+function removeExtras(object) {
+ if (!defined(object.extras)) {
+ return;
+ }
- if (defined(object.extras._pipeline)) {
- delete object.extras._pipeline;
- }
+ if (defined(object.extras._pipeline)) {
+ delete object.extras._pipeline;
+ }
- if (Object.keys(object.extras).length === 0) {
- delete object.extras;
- }
+ if (Object.keys(object.extras).length === 0) {
+ delete object.extras;
}
+}
- export default removePipelineExtras;
+export default removePipelineExtras;
diff --git a/Source/ThirdParty/GltfPipeline/removeUnusedElements.js b/Source/ThirdParty/GltfPipeline/removeUnusedElements.js
index c7b5789c6a54..1852368da75b 100644
--- a/Source/ThirdParty/GltfPipeline/removeUnusedElements.js
+++ b/Source/ThirdParty/GltfPipeline/removeUnusedElements.js
@@ -1,428 +1,655 @@
-import ForEach from './ForEach.js'
-import usesExtension from './usesExtension.js'
-import defaultValue from '../../Core/defaultValue.js'
-import defined from '../../Core/defined.js'
-
- var allElementTypes = ['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer'];
-
- /**
- * Removes unused elements from gltf.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @param {String[]} [elementTypes=['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer']] Element types to be removed. Needs to be a subset of ['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer'], other items will be ignored.
- *
- * @private
- */
- function removeUnusedElements(gltf, elementTypes) {
- elementTypes = defaultValue(elementTypes, allElementTypes);
- allElementTypes.forEach(function(type) {
- if (elementTypes.indexOf(type) > -1) {
- removeUnusedElementsByType(gltf, type);
- }
- });
- return gltf;
- }
-
- var TypeToGltfElementName = {
- accessor: 'accessors',
- buffer: 'buffers',
- bufferView: 'bufferViews',
- node: 'nodes',
- material: 'materials',
- mesh: 'meshes'
- };
-
- function removeUnusedElementsByType(gltf, type) {
- var name = TypeToGltfElementName[type];
- var arrayOfObjects = gltf[name];
-
- if (defined(arrayOfObjects)) {
- var removed = 0;
- var usedIds = getListOfElementsIdsInUse[type](gltf);
- var length = arrayOfObjects.length;
-
- for (var i = 0; i < length; ++i) {
- if (!usedIds[i]) {
- Remove[type](gltf, i - removed);
- removed++;
- }
+import ForEach from "./ForEach.js"
+import forEachTextureInMaterial from "./forEachTextureInMaterial.js"
+import usesExtension from "./usesExtension.js"
+import defaultValue from "../../Core/defaultValue.js"
+import defined from "../../Core/defined.js"
+
+var allElementTypes = ['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer', 'texture', 'sampler', 'image'];
+
+/**
+ * Removes unused elements from gltf.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @param {String[]} [elementTypes=['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer']] Element types to be removed. Needs to be a subset of ['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer'], other items will be ignored.
+ *
+ * @private
+ */
+function removeUnusedElements(gltf, elementTypes) {
+ elementTypes = defaultValue(elementTypes, allElementTypes);
+ allElementTypes.forEach(function(type) {
+ if (elementTypes.indexOf(type) > -1) {
+ removeUnusedElementsByType(gltf, type);
+ }
+ });
+ return gltf;
+}
+
+var TypeToGltfElementName = {
+ accessor: 'accessors',
+ buffer: 'buffers',
+ bufferView: 'bufferViews',
+ image: 'images',
+ node: 'nodes',
+ material: 'materials',
+ mesh: 'meshes',
+ sampler: 'samplers',
+ texture: 'textures'
+};
+
+function removeUnusedElementsByType(gltf, type) {
+ var name = TypeToGltfElementName[type];
+ var arrayOfObjects = gltf[name];
+
+ if (defined(arrayOfObjects)) {
+ var removed = 0;
+ var usedIds = getListOfElementsIdsInUse[type](gltf);
+ var length = arrayOfObjects.length;
+
+ for (var i = 0; i < length; ++i) {
+ if (!usedIds[i]) {
+ Remove[type](gltf, i - removed);
+ removed++;
}
}
}
+}
+
+/**
+ * Contains functions for removing elements from a glTF hierarchy.
+ * Since top-level glTF elements are arrays, when something is removed, referring
+ * indices need to be updated.
+ * @constructor
+ *
+ * @private
+ */
+function Remove() {}
+
+Remove.accessor = function(gltf, accessorId) {
+ var accessors = gltf.accessors;
+
+ accessors.splice(accessorId, 1);
+
+ ForEach.mesh(gltf, function(mesh) {
+ ForEach.meshPrimitive(mesh, function(primitive) {
+ // Update accessor ids for the primitives.
+ ForEach.meshPrimitiveAttribute(primitive, function(attributeAccessorId, semantic) {
+ if (attributeAccessorId > accessorId) {
+ primitive.attributes[semantic]--;
+ }
+ });
- /**
- * Contains functions for removing elements from a glTF hierarchy.
- * Since top-level glTF elements are arrays, when something is removed, referring
- * indices need to be updated.
- * @constructor
- *
- * @private
- */
- function Remove() {}
-
- Remove.accessor = function(gltf, accessorId) {
- var accessors = gltf.accessors;
-
- accessors.splice(accessorId, 1);
-
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- // Update accessor ids for the primitives.
- ForEach.meshPrimitiveAttribute(primitive, function(attributeAccessorId, semantic) {
+ // Update accessor ids for the targets.
+ ForEach.meshPrimitiveTarget(primitive, function(target) {
+ ForEach.meshPrimitiveTargetAttribute(target, function(attributeAccessorId, semantic) {
if (attributeAccessorId > accessorId) {
- primitive.attributes[semantic]--;
+ target[semantic]--;
}
});
-
- // Update accessor ids for the targets.
- ForEach.meshPrimitiveTarget(primitive, function(target) {
- ForEach.meshPrimitiveTargetAttribute(target, function(attributeAccessorId, semantic) {
- if (attributeAccessorId > accessorId) {
- target[semantic]--;
- }
- });
- });
- var indices = primitive.indices;
- if (defined(indices) && indices > accessorId) {
- primitive.indices--;
- }
});
+ var indices = primitive.indices;
+ if (defined(indices) && indices > accessorId) {
+ primitive.indices--;
+ }
});
+ });
+
+ ForEach.skin(gltf, function(skin) {
+ if (defined(skin.inverseBindMatrices) && skin.inverseBindMatrices > accessorId) {
+ skin.inverseBindMatrices--;
+ }
+ });
- ForEach.skin(gltf, function(skin) {
- if (defined(skin.inverseBindMatrices) && skin.inverseBindMatrices > accessorId) {
- skin.inverseBindMatrices--;
+ ForEach.animation(gltf, function(animation) {
+ ForEach.animationSampler(animation, function(sampler) {
+ if (defined(sampler.input) && sampler.input > accessorId) {
+ sampler.input--;
+ }
+ if (defined(sampler.output) && sampler.output > accessorId) {
+ sampler.output--;
}
});
+ });
+};
- ForEach.animation(gltf, function(animation) {
- ForEach.animationSampler(animation, function(sampler) {
- if (defined(sampler.input) && sampler.input > accessorId) {
- sampler.input--;
- }
- if (defined(sampler.output) && sampler.output > accessorId) {
- sampler.output--;
- }
- });
- });
- };
+Remove.buffer = function(gltf, bufferId) {
+ var buffers = gltf.buffers;
- Remove.buffer = function(gltf, bufferId) {
- var buffers = gltf.buffers;
+ buffers.splice(bufferId, 1);
- buffers.splice(bufferId, 1);
+ ForEach.bufferView(gltf, function(bufferView) {
+ if (defined(bufferView.buffer) && bufferView.buffer > bufferId) {
+ bufferView.buffer--;
+ }
+ });
+};
- ForEach.bufferView(gltf, function(bufferView) {
- if (defined(bufferView.buffer) && bufferView.buffer > bufferId) {
- bufferView.buffer--;
- }
- });
- };
+Remove.bufferView = function(gltf, bufferViewId) {
+ var bufferViews = gltf.bufferViews;
- Remove.bufferView = function(gltf, bufferViewId) {
- var bufferViews = gltf.bufferViews;
+ bufferViews.splice(bufferViewId, 1);
- bufferViews.splice(bufferViewId, 1);
+ ForEach.accessor(gltf, function(accessor) {
+ if (defined(accessor.bufferView) && accessor.bufferView > bufferViewId) {
+ accessor.bufferView--;
+ }
+ });
- ForEach.accessor(gltf, function(accessor) {
- if (defined(accessor.bufferView) && accessor.bufferView > bufferViewId) {
- accessor.bufferView--;
- }
- });
+ ForEach.shader(gltf, function(shader) {
+ if (defined(shader.bufferView) && shader.bufferView > bufferViewId) {
+ shader.bufferView--;
+ }
+ });
- ForEach.shader(gltf, function(shader) {
- if (defined(shader.bufferView) && shader.bufferView > bufferViewId) {
- shader.bufferView--;
- }
- });
+ ForEach.image(gltf, function(image) {
+ if (defined(image.bufferView) && image.bufferView > bufferViewId) {
+ image.bufferView--;
+ }
+ });
- ForEach.image(gltf, function(image) {
- if (defined(image.bufferView) && image.bufferView > bufferViewId) {
- image.bufferView--;
- }
- ForEach.compressedImage(image, function(compressedImage) {
- var compressedImageBufferView = compressedImage.bufferView;
- if (defined(compressedImageBufferView) && compressedImageBufferView > bufferViewId) {
- compressedImage.bufferView--;
+ if (usesExtension(gltf, 'KHR_draco_mesh_compression')) {
+ ForEach.mesh(gltf, function(mesh) {
+ ForEach.meshPrimitive(mesh, function(primitive) {
+ if (defined(primitive.extensions) &&
+ defined(primitive.extensions.KHR_draco_mesh_compression)) {
+ if (primitive.extensions.KHR_draco_mesh_compression.bufferView > bufferViewId) {
+ primitive.extensions.KHR_draco_mesh_compression.bufferView--;
+ }
}
});
});
+ }
- if (usesExtension(gltf, 'KHR_draco_mesh_compression')) {
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- if (defined(primitive.extensions) &&
- defined(primitive.extensions.KHR_draco_mesh_compression)) {
- if (primitive.extensions.KHR_draco_mesh_compression.bufferView > bufferViewId) {
- primitive.extensions.KHR_draco_mesh_compression.bufferView--;
+ if (usesExtension(gltf, 'EXT_feature_metadata')) {
+ var extension = gltf.extensions.EXT_feature_metadata;
+ var featureTables = extension.featureTables;
+ for (var featureTableId in featureTables) {
+ if (featureTables.hasOwnProperty(featureTableId)) {
+ var featureTable = featureTables[featureTableId];
+ var properties = featureTable.properties;
+ if (defined(properties)) {
+ for (var propertyId in properties) {
+ if (properties.hasOwnProperty(propertyId)) {
+ var property = properties[propertyId];
+ if (defined(property.bufferView) && property.bufferView > bufferViewId) {
+ property.bufferView--;
+ }
+ if (defined(property.arrayOffsetBufferView) && property.arrayOffsetBufferView > bufferViewId) {
+ property.arrayOffsetBufferView--;
+ }
+ if (defined(property.stringOffsetBufferView) && property.stringOffsetBufferView > bufferViewId) {
+ property.stringOffsetBufferView--;
+ }
}
}
- });
- });
+ }
+ }
}
- };
+ }
+};
- Remove.mesh = function(gltf, meshId) {
- var meshes = gltf.meshes;
- meshes.splice(meshId, 1);
+Remove.image = function(gltf, imageId) {
+ var images = gltf.images;
+ images.splice(imageId, 1);
- ForEach.node(gltf, function(node) {
- if (defined(node.mesh)) {
- if (node.mesh > meshId) {
- node.mesh--;
- } else if (node.mesh === meshId) {
- // Remove reference to deleted mesh
- delete node.mesh;
- }
+ ForEach.texture(gltf, function (texture) {
+ if (defined(texture.source)) {
+ if (texture.source > imageId) {
+ --texture.source;
}
- });
- };
+ }
+ var ext = texture.extensions;
+ if (defined(ext) && defined(ext.EXT_texture_webp) && ext.EXT_texture_webp.source > imageId) {
+ --texture.extensions.EXT_texture_webp.source;
+ } else if (defined(ext) && defined(ext.KHR_texture_basisu) && ext.KHR_texture_basisu.source > imageId) {
+ --texture.extensions.KHR_texture_basisu.source;
+ }
+ });
+};
+
+Remove.mesh = function(gltf, meshId) {
+ var meshes = gltf.meshes;
+ meshes.splice(meshId, 1);
+
+ ForEach.node(gltf, function(node) {
+ if (defined(node.mesh)) {
+ if (node.mesh > meshId) {
+ node.mesh--;
+ } else if (node.mesh === meshId) {
+ // Remove reference to deleted mesh
+ delete node.mesh;
+ }
+ }
+ });
+};
- Remove.node = function(gltf, nodeId) {
- var nodes = gltf.nodes;
- nodes.splice(nodeId, 1);
+Remove.node = function(gltf, nodeId) {
+ var nodes = gltf.nodes;
+ nodes.splice(nodeId, 1);
- // Shift all node references
- ForEach.skin(gltf, function(skin) {
- if (defined(skin.skeleton) && skin.skeleton > nodeId) {
- skin.skeleton--;
- }
+ // Shift all node references
+ ForEach.skin(gltf, function(skin) {
+ if (defined(skin.skeleton) && skin.skeleton > nodeId) {
+ skin.skeleton--;
+ }
- skin.joints = skin.joints.map(function(x) {
- return x > nodeId ? x - 1 : x;
- });
+ skin.joints = skin.joints.map(function(x) {
+ return x > nodeId ? x - 1 : x;
});
- ForEach.animation(gltf, function(animation) {
- ForEach.animationChannel(animation, function(channel) {
- if (defined(channel.target) && defined(channel.target.node) && (channel.target.node > nodeId)) {
- channel.target.node--;
- }
- });
+ });
+ ForEach.animation(gltf, function(animation) {
+ ForEach.animationChannel(animation, function(channel) {
+ if (defined(channel.target) && defined(channel.target.node) && (channel.target.node > nodeId)) {
+ channel.target.node--;
+ }
});
- ForEach.technique(gltf, function(technique) {
- ForEach.techniqueUniform(technique, function(uniform) {
- if (defined(uniform.node) && uniform.node > nodeId) {
- uniform.node--;
- }
+ });
+ ForEach.technique(gltf, function(technique) {
+ ForEach.techniqueUniform(technique, function(uniform) {
+ if (defined(uniform.node) && uniform.node > nodeId) {
+ uniform.node--;
+ }
+ });
+ });
+ ForEach.node(gltf, function(node) {
+ if (!defined(node.children)) {
+ return;
+ }
+
+ node.children = node.children
+ .filter(function(x) {
+ return x !== nodeId; // Remove
+ })
+ .map(function(x) {
+ return x > nodeId ? x - 1 : x; // Shift indices
});
+ });
+ ForEach.scene(gltf, function(scene) {
+ scene.nodes = scene.nodes
+ .filter(function(x) {
+ return x !== nodeId; // Remove
+ })
+ .map(function(x) {
+ return x > nodeId ? x - 1 : x; // Shift indices
+ });
+ });
+};
+
+Remove.material = function(gltf, materialId) {
+ var materials = gltf.materials;
+ materials.splice(materialId, 1);
+
+ // Shift other material ids
+ ForEach.mesh(gltf, function(mesh) {
+ ForEach.meshPrimitive(mesh, function(primitive) {
+ if (defined(primitive.material) && primitive.material > materialId) {
+ primitive.material--;
+ }
});
- ForEach.node(gltf, function(node) {
- if (!defined(node.children)) {
- return;
+ });
+};
+
+Remove.sampler = function(gltf, samplerId) {
+ var samplers = gltf.samplers;
+ samplers.splice(samplerId, 1);
+
+ ForEach.texture(gltf, function (texture) {
+ if (defined(texture.sampler)) {
+ if (texture.sampler > samplerId) {
+ --texture.sampler;
}
+ }
+ });
+};
- node.children = node.children
- .filter(function(x) {
- return x !== nodeId; // Remove
- })
- .map(function(x) {
- return x > nodeId ? x - 1 : x; // Shift indices
- });
- });
- ForEach.scene(gltf, function(scene) {
- scene.nodes = scene.nodes
- .filter(function(x) {
- return x !== nodeId; // Remove
- })
- .map(function(x) {
- return x > nodeId ? x - 1 : x; // Shift indices
- });
- });
- };
+Remove.texture = function(gltf, textureId) {
+ var textures = gltf.textures;
+ textures.splice(textureId, 1);
- Remove.material = function(gltf, materialId) {
- var materials = gltf.materials;
- materials.splice(materialId, 1);
+ ForEach.material(gltf, function (material) {
+ forEachTextureInMaterial(material, function (textureIndex, textureInfo) {
+ if (textureInfo.index > textureId) {
+ --textureInfo.index;
+ }
+ });
+ });
- // Shift other material ids
+ if (usesExtension(gltf, 'EXT_feature_metadata')) {
ForEach.mesh(gltf, function(mesh) {
ForEach.meshPrimitive(mesh, function(primitive) {
- if (defined(primitive.material) && primitive.material > materialId) {
- primitive.material--;
+ var extensions = primitive.extensions;
+ if (defined(extensions) && defined(extensions.EXT_feature_metadata)) {
+ var extension = extensions.EXT_feature_metadata;
+ var featureIdTextures = extension.featureIdTextures;
+ if (defined(featureIdTextures)) {
+ var featureIdTexturesLength = featureIdTextures.length;
+ for (var i = 0; i < featureIdTexturesLength; ++i) {
+ var featureIdTexture = featureIdTextures[i];
+ var textureInfo = featureIdTexture.featureIds.texture;
+ if (textureInfo.index > textureId) {
+ --textureInfo.index;
+ }
+ }
+ }
}
});
});
- };
-
- /**
- * Contains functions for getting a list of element ids in use by the glTF asset.
- * @constructor
- *
- * @private
- */
- function getListOfElementsIdsInUse() {}
- getListOfElementsIdsInUse.accessor = function(gltf) {
- // Calculate accessor's that are currently in use.
- var usedAccessorIds = {};
-
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- ForEach.meshPrimitiveAttribute(primitive, function(accessorId) {
+ var extension = gltf.extensions.EXT_feature_metadata;
+ var featureTextures = extension.featureTextures;
+ for (var featureTextureId in featureTextures) {
+ if (featureTextures.hasOwnProperty(featureTextureId)) {
+ var featureTexture = featureTextures[featureTextureId];
+ var properties = featureTexture.properties;
+ if (defined(properties)) {
+ for (var propertyId in properties) {
+ if (properties.hasOwnProperty(propertyId)) {
+ var property = properties[propertyId];
+ var textureInfo = property.texture;
+ if (textureInfo.index > textureId) {
+ --textureInfo.index;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+};
+
+/**
+ * Contains functions for getting a list of element ids in use by the glTF asset.
+ * @constructor
+ *
+ * @private
+ */
+function getListOfElementsIdsInUse() {}
+
+getListOfElementsIdsInUse.accessor = function(gltf) {
+ // Calculate accessor's that are currently in use.
+ var usedAccessorIds = {};
+
+ ForEach.mesh(gltf, function(mesh) {
+ ForEach.meshPrimitive(mesh, function(primitive) {
+ ForEach.meshPrimitiveAttribute(primitive, function(accessorId) {
+ usedAccessorIds[accessorId] = true;
+ });
+ ForEach.meshPrimitiveTarget(primitive, function(target) {
+ ForEach.meshPrimitiveTargetAttribute(target, function(accessorId) {
usedAccessorIds[accessorId] = true;
});
- ForEach.meshPrimitiveTarget(primitive, function(target) {
- ForEach.meshPrimitiveTargetAttribute(target, function(accessorId) {
- usedAccessorIds[accessorId] = true;
- });
- });
- var indices = primitive.indices;
- if (defined(indices)) {
- usedAccessorIds[indices] = true;
- }
});
+ var indices = primitive.indices;
+ if (defined(indices)) {
+ usedAccessorIds[indices] = true;
+ }
});
+ });
+
+ ForEach.skin(gltf, function(skin) {
+ if (defined(skin.inverseBindMatrices)) {
+ usedAccessorIds[skin.inverseBindMatrices] = true;
+ }
+ });
- ForEach.skin(gltf, function(skin) {
- if (defined(skin.inverseBindMatrices)) {
- usedAccessorIds[skin.inverseBindMatrices] = true;
+ ForEach.animation(gltf, function(animation) {
+ ForEach.animationSampler(animation, function(sampler) {
+ if (defined(sampler.input)) {
+ usedAccessorIds[sampler.input] = true;
+ }
+ if (defined(sampler.output)) {
+ usedAccessorIds[sampler.output] = true;
}
});
+ });
- ForEach.animation(gltf, function(animation) {
- ForEach.animationSampler(animation, function(sampler) {
- if (defined(sampler.input)) {
- usedAccessorIds[sampler.input] = true;
- }
- if (defined(sampler.output)) {
- usedAccessorIds[sampler.output] = true;
- }
- });
+ if (usesExtension(gltf, 'EXT_mesh_gpu_instancing')) {
+ ForEach.node(gltf, function(node) {
+ if (defined(node.extensions) && defined(node.extensions.EXT_mesh_gpu_instancing)) {
+ Object.keys(node.extensions.EXT_mesh_gpu_instancing.attributes).forEach(function(key) {
+ var attributeAccessorId = node.extensions.EXT_mesh_gpu_instancing.attributes[key];
+ usedAccessorIds[attributeAccessorId] = true;
+ });
+ }
});
+ }
- return usedAccessorIds;
- };
+ return usedAccessorIds;
+};
- getListOfElementsIdsInUse.buffer = function(gltf) {
- // Calculate buffer's that are currently in use.
- var usedBufferIds = {};
+getListOfElementsIdsInUse.buffer = function(gltf) {
+ // Calculate buffer's that are currently in use.
+ var usedBufferIds = {};
- ForEach.bufferView(gltf, function(bufferView) {
- if (defined(bufferView.buffer)) {
- usedBufferIds[bufferView.buffer] = true;
- }
- });
+ ForEach.bufferView(gltf, function(bufferView) {
+ if (defined(bufferView.buffer)) {
+ usedBufferIds[bufferView.buffer] = true;
+ }
+ });
- return usedBufferIds;
- };
+ return usedBufferIds;
+};
- getListOfElementsIdsInUse.bufferView = function(gltf) {
- // Calculate bufferView's that are currently in use.
- var usedBufferViewIds = {};
+getListOfElementsIdsInUse.bufferView = function(gltf) {
+ // Calculate bufferView's that are currently in use.
+ var usedBufferViewIds = {};
- ForEach.accessor(gltf, function(accessor) {
- if (defined(accessor.bufferView)) {
- usedBufferViewIds[accessor.bufferView] = true;
- }
- });
+ ForEach.accessor(gltf, function(accessor) {
+ if (defined(accessor.bufferView)) {
+ usedBufferViewIds[accessor.bufferView] = true;
+ }
+ });
- ForEach.shader(gltf, function(shader) {
- if (defined(shader.bufferView)) {
- usedBufferViewIds[shader.bufferView] = true;
- }
- });
+ ForEach.shader(gltf, function(shader) {
+ if (defined(shader.bufferView)) {
+ usedBufferViewIds[shader.bufferView] = true;
+ }
+ });
- ForEach.image(gltf, function(image) {
- if (defined(image.bufferView)) {
- usedBufferViewIds[image.bufferView] = true;
- }
- ForEach.compressedImage(image, function(compressedImage) {
- if (defined(compressedImage.bufferView)) {
- usedBufferViewIds[compressedImage.bufferView] = true;
+ ForEach.image(gltf, function(image) {
+ if (defined(image.bufferView)) {
+ usedBufferViewIds[image.bufferView] = true;
+ }
+ });
+
+ if (usesExtension(gltf, 'KHR_draco_mesh_compression')) {
+ ForEach.mesh(gltf, function(mesh) {
+ ForEach.meshPrimitive(mesh, function(primitive) {
+ if (defined(primitive.extensions) &&
+ defined(primitive.extensions.KHR_draco_mesh_compression)) {
+ usedBufferViewIds[primitive.extensions.KHR_draco_mesh_compression.bufferView] = true;
}
});
});
+ }
- if (usesExtension(gltf, 'KHR_draco_mesh_compression')) {
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- if (defined(primitive.extensions) &&
- defined(primitive.extensions.KHR_draco_mesh_compression)) {
- usedBufferViewIds[primitive.extensions.KHR_draco_mesh_compression.bufferView] = true;
+ if (usesExtension(gltf, 'EXT_feature_metadata')) {
+ var extension = gltf.extensions.EXT_feature_metadata;
+ var featureTables = extension.featureTables;
+ for (var featureTableId in featureTables) {
+ if (featureTables.hasOwnProperty(featureTableId)) {
+ var featureTable = featureTables[featureTableId];
+ var properties = featureTable.properties;
+ if (defined(properties)) {
+ for (var propertyId in properties) {
+ if (properties.hasOwnProperty(propertyId)) {
+ var property = properties[propertyId];
+ if (defined(property.bufferView)) {
+ usedBufferViewIds[property.bufferView] = true;
+ }
+ if (defined(property.arrayOffsetBufferView)) {
+ usedBufferViewIds[property.arrayOffsetBufferView] = true;
+ }
+ if (defined(property.stringOffsetBufferView)) {
+ usedBufferViewIds[property.stringOffsetBufferView] = true;
+ }
+ }
}
- });
- });
+ }
+ }
}
+ }
- return usedBufferViewIds;
- };
+ return usedBufferViewIds;
+};
- getListOfElementsIdsInUse.mesh = function(gltf) {
- var usedMeshIds = {};
- ForEach.node(gltf, function(node) {
- if (defined(node.mesh && defined(gltf.meshes))) {
- var mesh = gltf.meshes[node.mesh];
- if (defined(mesh) && defined(mesh.primitives) && (mesh.primitives.length > 0)) {
- usedMeshIds[node.mesh] = true;
- }
- }
- });
+getListOfElementsIdsInUse.image = function(gltf) {
+ var usedImageIds = {};
- return usedMeshIds;
- };
+ ForEach.texture(gltf, function (texture) {
+ if (defined(texture.source)) {
+ usedImageIds[texture.source] = true;
+ }
- // Check if node is empty. It is considered empty if neither referencing
- // mesh, camera, extensions and has no children
- function nodeIsEmpty(gltf, node) {
- if (defined(node.mesh) || defined(node.camera) || defined(node.skin)
- || defined(node.weights) || defined(node.extras)
- || (defined(node.extensions) && node.extensions.length !== 0)) {
- return false;
+ if (defined(texture.extensions) && defined(texture.extensions.EXT_texture_webp)) {
+ usedImageIds[texture.extensions.EXT_texture_webp.source] = true;
+ } else if (defined(texture.extensions) && defined(texture.extensions.KHR_texture_basisu)) {
+ usedImageIds[texture.extensions.KHR_texture_basisu.source] = true;
}
- // Empty if no children or children are all empty nodes
- return !defined(node.children)
- || node.children.filter(function(n) {
- return !nodeIsEmpty(gltf, gltf.nodes[n]);
- }).length === 0;
+ });
+ return usedImageIds;
+};
+
+getListOfElementsIdsInUse.mesh = function(gltf) {
+ var usedMeshIds = {};
+ ForEach.node(gltf, function(node) {
+ if (defined(node.mesh && defined(gltf.meshes))) {
+ var mesh = gltf.meshes[node.mesh];
+ if (defined(mesh) && defined(mesh.primitives) && (mesh.primitives.length > 0)) {
+ usedMeshIds[node.mesh] = true;
+ }
+ }
+ });
+
+ return usedMeshIds;
+};
+
+// Check if node is empty. It is considered empty if neither referencing
+// mesh, camera, extensions and has no children
+function nodeIsEmpty(gltf, nodeId, usedNodeIds) {
+ var node = gltf.nodes[nodeId];
+ if (defined(node.mesh) || defined(node.camera) || defined(node.skin)
+ || defined(node.weights) || defined(node.extras)
+ || (defined(node.extensions) && Object.keys(node.extensions).length !== 0)
+ || defined(usedNodeIds[nodeId])) {
+ return false;
}
- getListOfElementsIdsInUse.node = function(gltf) {
- var usedNodeIds = {};
- ForEach.node(gltf, function(node, nodeId) {
- if (!nodeIsEmpty(gltf, node)) {
- usedNodeIds[nodeId] = true;
- }
+ // Empty if no children or children are all empty nodes
+ return !defined(node.children)
+ || node.children.filter(function(n) {
+ return !nodeIsEmpty(gltf, n, usedNodeIds);
+ }).length === 0;
+}
+
+getListOfElementsIdsInUse.node = function(gltf) {
+ var usedNodeIds = {};
+ ForEach.skin(gltf, function(skin) {
+ if (defined(skin.skeleton)) {
+ usedNodeIds[skin.skeleton] = true;
+ }
+
+ ForEach.skinJoint(skin, function(joint) {
+ usedNodeIds[joint] = true;
});
- ForEach.skin(gltf, function(skin) {
- if (defined(skin.skeleton)) {
- usedNodeIds[skin.skeleton] = true;
+ });
+ ForEach.animation(gltf, function(animation) {
+ ForEach.animationChannel(animation, function(channel) {
+ if (defined(channel.target) && defined(channel.target.node)) {
+ usedNodeIds[channel.target.node] = true;
}
-
- ForEach.skinJoint(skin, function(joint) {
- usedNodeIds[joint] = true;
- });
});
- ForEach.animation(gltf, function(animation) {
- ForEach.animationChannel(animation, function(channel) {
- if (defined(channel.target) && defined(channel.target.node)) {
- usedNodeIds[channel.target.node] = true;
- }
- });
+ });
+ ForEach.technique(gltf, function(technique) {
+ ForEach.techniqueUniform(technique, function(uniform) {
+ if (defined(uniform.node)) {
+ usedNodeIds[uniform.node] = true;
+ }
});
- ForEach.technique(gltf, function(technique) {
- ForEach.techniqueUniform(technique, function(uniform) {
- if (defined(uniform.node)) {
- usedNodeIds[uniform.node] = true;
- }
- });
+ });
+ ForEach.node(gltf, function(node, nodeId) {
+ if (!nodeIsEmpty(gltf, nodeId, usedNodeIds)) {
+ usedNodeIds[nodeId] = true;
+ }
+ });
+
+ return usedNodeIds;
+};
+
+getListOfElementsIdsInUse.material = function(gltf) {
+ var usedMaterialIds = {};
+
+ ForEach.mesh(gltf, function(mesh) {
+ ForEach.meshPrimitive(mesh, function(primitive) {
+ if (defined(primitive.material)) {
+ usedMaterialIds[primitive.material] = true;
+ }
});
+ });
+
+ return usedMaterialIds;
+};
- return usedNodeIds;
- };
+getListOfElementsIdsInUse.texture = function(gltf) {
+ var usedTextureIds = {};
- getListOfElementsIdsInUse.material = function(gltf) {
- var usedMaterialIds = {};
+ ForEach.material(gltf, function(material) {
+ forEachTextureInMaterial(material, function(textureId) {
+ usedTextureIds[textureId] = true;
+ });
+ });
+ if (usesExtension(gltf, 'EXT_feature_metadata')) {
ForEach.mesh(gltf, function(mesh) {
ForEach.meshPrimitive(mesh, function(primitive) {
- if (defined(primitive.material)) {
- usedMaterialIds[primitive.material] = true;
+ var extensions = primitive.extensions;
+ if (defined(extensions) && defined(extensions.EXT_feature_metadata)) {
+ var extension = extensions.EXT_feature_metadata;
+ var featureIdTextures = extension.featureIdTextures;
+ if (defined(featureIdTextures)) {
+ var featureIdTexturesLength = featureIdTextures.length;
+ for (var i = 0; i < featureIdTexturesLength; ++i) {
+ var featureIdTexture = featureIdTextures[i];
+ var textureInfo = featureIdTexture.featureIds.texture;
+ usedTextureIds[textureInfo.index] = true;
+ }
+ }
}
});
});
- return usedMaterialIds;
- };
+ var extension = gltf.extensions.EXT_feature_metadata;
+ var featureTextures = extension.featureTextures;
+ for (var featureTextureId in featureTextures) {
+ if (featureTextures.hasOwnProperty(featureTextureId)) {
+ var featureTexture = featureTextures[featureTextureId];
+ var properties = featureTexture.properties;
+ if (defined(properties)) {
+ for (var propertyId in properties) {
+ if (properties.hasOwnProperty(propertyId)) {
+ var property = properties[propertyId];
+ var textureInfo = property.texture;
+ usedTextureIds[textureInfo.index] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return usedTextureIds;
+};
+
+getListOfElementsIdsInUse.sampler = function(gltf) {
+ var usedSamplerIds = {};
+
+ ForEach.texture(gltf, function (texture) {
+ if (defined(texture.sampler)) {
+ usedSamplerIds[texture.sampler] = true;
+ }
+ });
+
+ return usedSamplerIds;
+};
- export default removeUnusedElements;
+export default removeUnusedElements;
diff --git a/Source/ThirdParty/GltfPipeline/updateAccessorComponentTypes.js b/Source/ThirdParty/GltfPipeline/updateAccessorComponentTypes.js
index 1efcb7bfe76e..fd035af0723e 100644
--- a/Source/ThirdParty/GltfPipeline/updateAccessorComponentTypes.js
+++ b/Source/ThirdParty/GltfPipeline/updateAccessorComponentTypes.js
@@ -1,48 +1,48 @@
-import addBuffer from './addBuffer.js'
-import ForEach from './ForEach.js'
-import readAccessorPacked from './readAccessorPacked.js'
-import ComponentDatatype from '../../Core/ComponentDatatype.js'
-import WebGLConstants from '../../Core/WebGLConstants.js'
+import addBuffer from "./addBuffer.js"
+import ForEach from "./ForEach.js"
+import readAccessorPacked from "./readAccessorPacked.js"
+import ComponentDatatype from "../../Core/ComponentDatatype.js"
+import WebGLConstants from "../../Core/WebGLConstants.js"
- /**
- * Update accessors referenced by JOINTS_0 and WEIGHTS_0 attributes to use correct component types.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @returns {Object} The glTF asset with compressed meshes.
- *
- * @private
- */
- function updateAccessorComponentTypes(gltf) {
- var componentType;
- ForEach.accessorWithSemantic(gltf, 'JOINTS_0', function(accessorId) {
- var accessor = gltf.accessors[accessorId];
- componentType = accessor.componentType;
- if (componentType === WebGLConstants.BYTE) {
- convertType(gltf, accessor, ComponentDatatype.UNSIGNED_BYTE);
- } else if (componentType !== WebGLConstants.UNSIGNED_BYTE
- && componentType !== WebGLConstants.UNSIGNED_SHORT) {
- convertType(gltf, accessor, ComponentDatatype.UNSIGNED_SHORT);
- }
- });
- ForEach.accessorWithSemantic(gltf, 'WEIGHTS_0', function(accessorId) {
- var accessor = gltf.accessors[accessorId];
- componentType = accessor.componentType;
- if (componentType === WebGLConstants.BYTE) {
- convertType(gltf, accessor, ComponentDatatype.UNSIGNED_BYTE);
- } else if (componentType === WebGLConstants.SHORT) {
- convertType(gltf, accessor, ComponentDatatype.UNSIGNED_SHORT);
- }
- });
+/**
+ * Update accessors referenced by JOINTS_0 and WEIGHTS_0 attributes to use correct component types.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @returns {Object} The glTF asset with compressed meshes.
+ *
+ * @private
+ */
+function updateAccessorComponentTypes(gltf) {
+ var componentType;
+ ForEach.accessorWithSemantic(gltf, 'JOINTS_0', function(accessorId) {
+ var accessor = gltf.accessors[accessorId];
+ componentType = accessor.componentType;
+ if (componentType === WebGLConstants.BYTE) {
+ convertType(gltf, accessor, ComponentDatatype.UNSIGNED_BYTE);
+ } else if (componentType !== WebGLConstants.UNSIGNED_BYTE
+ && componentType !== WebGLConstants.UNSIGNED_SHORT) {
+ convertType(gltf, accessor, ComponentDatatype.UNSIGNED_SHORT);
+ }
+ });
+ ForEach.accessorWithSemantic(gltf, 'WEIGHTS_0', function(accessorId) {
+ var accessor = gltf.accessors[accessorId];
+ componentType = accessor.componentType;
+ if (componentType === WebGLConstants.BYTE) {
+ convertType(gltf, accessor, ComponentDatatype.UNSIGNED_BYTE);
+ } else if (componentType === WebGLConstants.SHORT) {
+ convertType(gltf, accessor, ComponentDatatype.UNSIGNED_SHORT);
+ }
+ });
- return gltf;
- }
+ return gltf;
+}
- function convertType(gltf, accessor, updatedComponentType) {
- var typedArray = ComponentDatatype.createTypedArray(updatedComponentType, readAccessorPacked(gltf, accessor));
- var newBuffer = new Uint8Array(typedArray.buffer);
- accessor.bufferView = addBuffer(gltf, newBuffer);
- accessor.componentType = updatedComponentType;
- accessor.byteOffset = 0;
- }
+function convertType(gltf, accessor, updatedComponentType) {
+ var typedArray = ComponentDatatype.createTypedArray(updatedComponentType, readAccessorPacked(gltf, accessor));
+ var newBuffer = new Uint8Array(typedArray.buffer);
+ accessor.bufferView = addBuffer(gltf, newBuffer);
+ accessor.componentType = updatedComponentType;
+ accessor.byteOffset = 0;
+}
- export default updateAccessorComponentTypes;
+export default updateAccessorComponentTypes;
diff --git a/Source/ThirdParty/GltfPipeline/updateVersion.js b/Source/ThirdParty/GltfPipeline/updateVersion.js
index dc4f91cf1cdd..10b579ff84d7 100644
--- a/Source/ThirdParty/GltfPipeline/updateVersion.js
+++ b/Source/ThirdParty/GltfPipeline/updateVersion.js
@@ -1,936 +1,922 @@
-import addExtensionsUsed from './addExtensionsUsed.js'
-import addToArray from './addToArray.js'
-import findAccessorMinMax from './findAccessorMinMax.js'
-import ForEach from './ForEach.js'
-import getAccessorByteStride from './getAccessorByteStride.js'
-import numberOfComponentsForType from './numberOfComponentsForType.js'
-import moveTechniqueRenderStates from './moveTechniqueRenderStates.js'
-import moveTechniquesToExtension from './moveTechniquesToExtension.js'
-import removeUnusedElements from './removeUnusedElements.js'
-import updateAccessorComponentTypes from './updateAccessorComponentTypes.js'
-import Cartesian3 from '../../Core/Cartesian3.js'
-import Cartesian4 from '../../Core/Cartesian4.js'
-import clone from '../../Core/clone.js'
-import ComponentDatatype from '../../Core/ComponentDatatype.js'
-import defaultValue from '../../Core/defaultValue.js'
-import defined from '../../Core/defined.js'
-import Matrix4 from '../../Core/Matrix4.js'
-import Quaternion from '../../Core/Quaternion.js'
-import WebGLConstants from '../../Core/WebGLConstants.js'
-
- var updateFunctions = {
- '0.8': glTF08to10,
- '1.0': glTF10to20,
- '2.0': undefined
- };
-
- /**
- * Update the glTF version to the latest version (2.0), or targetVersion if specified.
- * Applies changes made to the glTF spec between revisions so that the core library
- * only has to handle the latest version.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @param {Object} [options] Options for updating the glTF.
- * @param {String} [options.targetVersion] The glTF will be upgraded until it hits the specified version.
- * @returns {Object} The updated glTF asset.
- *
- * @private
- */
- function updateVersion(gltf, options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- var targetVersion = options.targetVersion;
- var version = gltf.version;
-
- gltf.asset = defaultValue(gltf.asset, {
- version: '1.0'
- });
-
- gltf.asset.version = defaultValue(gltf.asset.version, '1.0');
- version = defaultValue(version, gltf.asset.version).toString();
-
- // Invalid version
+import addExtensionsUsed from "./addExtensionsUsed.js"
+import addToArray from "./addToArray.js"
+import findAccessorMinMax from "./findAccessorMinMax.js"
+import ForEach from "./ForEach.js"
+import getAccessorByteStride from "./getAccessorByteStride.js"
+import numberOfComponentsForType from "./numberOfComponentsForType.js"
+import moveTechniqueRenderStates from "./moveTechniqueRenderStates.js"
+import moveTechniquesToExtension from "./moveTechniquesToExtension.js"
+import removeUnusedElements from "./removeUnusedElements.js"
+import updateAccessorComponentTypes from "./updateAccessorComponentTypes.js"
+import Cartesian3 from "../../Core/Cartesian3.js"
+import Cartesian4 from "../../Core/Cartesian4.js"
+import clone from "../../Core/clone.js"
+import ComponentDatatype from "../../Core/ComponentDatatype.js"
+import defaultValue from "../../Core/defaultValue.js"
+import defined from "../../Core/defined.js"
+import Matrix4 from "../../Core/Matrix4.js"
+import Quaternion from "../../Core/Quaternion.js"
+import WebGLConstants from "../../Core/WebGLConstants.js"
+
+var updateFunctions = {
+ '0.8': glTF08to10,
+ '1.0': glTF10to20,
+ '2.0': undefined
+};
+
+/**
+ * Update the glTF version to the latest version (2.0), or targetVersion if specified.
+ * Applies changes made to the glTF spec between revisions so that the core library
+ * only has to handle the latest version.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @param {Object} [options] Options for updating the glTF.
+ * @param {String} [options.targetVersion] The glTF will be upgraded until it hits the specified version.
+ * @returns {Object} The updated glTF asset.
+ *
+ * @private
+ */
+function updateVersion(gltf, options) {
+ options = defaultValue(options, defaultValue.EMPTY_OBJECT);
+ var targetVersion = options.targetVersion;
+ var version = gltf.version;
+
+ gltf.asset = defaultValue(gltf.asset, {
+ version: '1.0'
+ });
+
+ gltf.asset.version = defaultValue(gltf.asset.version, '1.0');
+ version = defaultValue(version, gltf.asset.version).toString();
+
+ // Invalid version
+ if (!Object.prototype.hasOwnProperty.call(updateFunctions, version)) {
+ // Try truncating trailing version numbers, could be a number as well if it is 0.8
+ if (defined(version)) {
+ version = version.substring(0, 3);
+ }
+ // Default to 1.0 if it cannot be determined
if (!Object.prototype.hasOwnProperty.call(updateFunctions, version)) {
- // Try truncating trailing version numbers, could be a number as well if it is 0.8
- if (defined(version)) {
- version = version.substring(0, 3);
- }
- // Default to 1.0 if it cannot be determined
- if (!Object.prototype.hasOwnProperty.call(updateFunctions, version)) {
- version = '1.0';
- }
+ version = '1.0';
}
+ }
- var updateFunction = updateFunctions[version];
+ var updateFunction = updateFunctions[version];
- while (defined(updateFunction)) {
- if (version === targetVersion) {
- break;
- }
- updateFunction(gltf, options);
- version = gltf.asset.version;
- updateFunction = updateFunctions[version];
+ while (defined(updateFunction)) {
+ if (version === targetVersion) {
+ break;
}
- return gltf;
+ updateFunction(gltf, options);
+ version = gltf.asset.version;
+ updateFunction = updateFunctions[version];
}
-
- function updateInstanceTechniques(gltf) {
- var materials = gltf.materials;
- for (var materialId in materials) {
- if (Object.prototype.hasOwnProperty.call(materials, materialId)) {
- var material = materials[materialId];
- var instanceTechnique = material.instanceTechnique;
- if (defined(instanceTechnique)) {
- material.technique = instanceTechnique.technique;
- material.values = instanceTechnique.values;
- delete material.instanceTechnique;
- }
+ return gltf;
+}
+
+function updateInstanceTechniques(gltf) {
+ var materials = gltf.materials;
+ for (var materialId in materials) {
+ if (Object.prototype.hasOwnProperty.call(materials, materialId)) {
+ var material = materials[materialId];
+ var instanceTechnique = material.instanceTechnique;
+ if (defined(instanceTechnique)) {
+ material.technique = instanceTechnique.technique;
+ material.values = instanceTechnique.values;
+ delete material.instanceTechnique;
}
}
}
-
- function setPrimitiveModes(gltf) {
- var meshes = gltf.meshes;
- for (var meshId in meshes) {
- if (Object.prototype.hasOwnProperty.call(meshes, meshId)) {
- var mesh = meshes[meshId];
- var primitives = mesh.primitives;
- if (defined(primitives)) {
- var primitivesLength = primitives.length;
- for (var i = 0; i < primitivesLength; ++i) {
- var primitive = primitives[i];
- var defaultMode = defaultValue(primitive.primitive, WebGLConstants.TRIANGLES);
- primitive.mode = defaultValue(primitive.mode, defaultMode);
- delete primitive.primitive;
- }
+}
+
+function setPrimitiveModes(gltf) {
+ var meshes = gltf.meshes;
+ for (var meshId in meshes) {
+ if (Object.prototype.hasOwnProperty.call(meshes, meshId)) {
+ var mesh = meshes[meshId];
+ var primitives = mesh.primitives;
+ if (defined(primitives)) {
+ var primitivesLength = primitives.length;
+ for (var i = 0; i < primitivesLength; ++i) {
+ var primitive = primitives[i];
+ var defaultMode = defaultValue(primitive.primitive, WebGLConstants.TRIANGLES);
+ primitive.mode = defaultValue(primitive.mode, defaultMode);
+ delete primitive.primitive;
}
}
}
}
-
- function updateNodes(gltf) {
- var nodes = gltf.nodes;
- var axis = new Cartesian3();
- var quat = new Quaternion();
- for (var nodeId in nodes) {
- if (Object.prototype.hasOwnProperty.call(nodes, nodeId)) {
- var node = nodes[nodeId];
- if (defined(node.rotation)) {
- var rotation = node.rotation;
- Cartesian3.fromArray(rotation, 0, axis);
- Quaternion.fromAxisAngle(axis, rotation[3], quat);
- node.rotation = [quat.x, quat.y, quat.z, quat.w];
- }
- var instanceSkin = node.instanceSkin;
- if (defined(instanceSkin)) {
- node.skeletons = instanceSkin.skeletons;
- node.skin = instanceSkin.skin;
- node.meshes = instanceSkin.meshes;
- delete node.instanceSkin;
- }
+}
+
+function updateNodes(gltf) {
+ var nodes = gltf.nodes;
+ var axis = new Cartesian3();
+ var quat = new Quaternion();
+ for (var nodeId in nodes) {
+ if (Object.prototype.hasOwnProperty.call(nodes, nodeId)) {
+ var node = nodes[nodeId];
+ if (defined(node.rotation)) {
+ var rotation = node.rotation;
+ Cartesian3.fromArray(rotation, 0, axis);
+ Quaternion.fromAxisAngle(axis, rotation[3], quat);
+ node.rotation = [quat.x, quat.y, quat.z, quat.w];
+ }
+ var instanceSkin = node.instanceSkin;
+ if (defined(instanceSkin)) {
+ node.skeletons = instanceSkin.skeletons;
+ node.skin = instanceSkin.skin;
+ node.meshes = instanceSkin.meshes;
+ delete node.instanceSkin;
}
}
}
-
- function updateAnimations(gltf) {
- var animations = gltf.animations;
- var accessors = gltf.accessors;
- var bufferViews = gltf.bufferViews;
- var buffers = gltf.buffers;
- var updatedAccessors = {};
- var axis = new Cartesian3();
- var quat = new Quaternion();
- for (var animationId in animations) {
- if (Object.prototype.hasOwnProperty.call(animations, animationId)) {
- var animation = animations[animationId];
- var channels = animation.channels;
- var parameters = animation.parameters;
- var samplers = animation.samplers;
- if (defined(channels)) {
- var channelsLength = channels.length;
- for (var i = 0; i < channelsLength; ++i) {
- var channel = channels[i];
- if (channel.target.path === 'rotation') {
- var accessorId = parameters[samplers[channel.sampler].output];
- if (defined(updatedAccessors[accessorId])) {
- continue;
- }
- updatedAccessors[accessorId] = true;
- var accessor = accessors[accessorId];
- var bufferView = bufferViews[accessor.bufferView];
- var buffer = buffers[bufferView.buffer];
- var source = buffer.extras._pipeline.source;
- var byteOffset = source.byteOffset + bufferView.byteOffset + accessor.byteOffset;
- var componentType = accessor.componentType;
- var count = accessor.count;
- var componentsLength = numberOfComponentsForType(accessor.type);
- var length = accessor.count * componentsLength;
- var typedArray = ComponentDatatype.createArrayBufferView(componentType, source.buffer, byteOffset, length);
-
- for (var j = 0; j < count; j++) {
- var offset = j * componentsLength;
- Cartesian3.unpack(typedArray, offset, axis);
- var angle = typedArray[offset + 3];
- Quaternion.fromAxisAngle(axis, angle, quat);
- Quaternion.pack(quat, typedArray, offset);
- }
+}
+
+function updateAnimations(gltf) {
+ var animations = gltf.animations;
+ var accessors = gltf.accessors;
+ var bufferViews = gltf.bufferViews;
+ var buffers = gltf.buffers;
+ var updatedAccessors = {};
+ var axis = new Cartesian3();
+ var quat = new Quaternion();
+ for (var animationId in animations) {
+ if (Object.prototype.hasOwnProperty.call(animations, animationId)) {
+ var animation = animations[animationId];
+ var channels = animation.channels;
+ var parameters = animation.parameters;
+ var samplers = animation.samplers;
+ if (defined(channels)) {
+ var channelsLength = channels.length;
+ for (var i = 0; i < channelsLength; ++i) {
+ var channel = channels[i];
+ if (channel.target.path === 'rotation') {
+ var accessorId = parameters[samplers[channel.sampler].output];
+ if (defined(updatedAccessors[accessorId])) {
+ continue;
+ }
+ updatedAccessors[accessorId] = true;
+ var accessor = accessors[accessorId];
+ var bufferView = bufferViews[accessor.bufferView];
+ var buffer = buffers[bufferView.buffer];
+ var source = buffer.extras._pipeline.source;
+ var byteOffset = source.byteOffset + bufferView.byteOffset + accessor.byteOffset;
+ var componentType = accessor.componentType;
+ var count = accessor.count;
+ var componentsLength = numberOfComponentsForType(accessor.type);
+ var length = accessor.count * componentsLength;
+ var typedArray = ComponentDatatype.createArrayBufferView(componentType, source.buffer, byteOffset, length);
+
+ for (var j = 0; j < count; j++) {
+ var offset = j * componentsLength;
+ Cartesian3.unpack(typedArray, offset, axis);
+ var angle = typedArray[offset + 3];
+ Quaternion.fromAxisAngle(axis, angle, quat);
+ Quaternion.pack(quat, typedArray, offset);
}
}
}
}
}
}
-
- function removeTechniquePasses(gltf) {
- var techniques = gltf.techniques;
- for (var techniqueId in techniques) {
- if (Object.prototype.hasOwnProperty.call(techniques, techniqueId)) {
- var technique = techniques[techniqueId];
- var passes = technique.passes;
- if (defined(passes)) {
- var passName = defaultValue(technique.pass, 'defaultPass');
- if (Object.prototype.hasOwnProperty.call(passes, passName)) {
- var pass = passes[passName];
- var instanceProgram = pass.instanceProgram;
- technique.attributes = defaultValue(technique.attributes, instanceProgram.attributes);
- technique.program = defaultValue(technique.program, instanceProgram.program);
- technique.uniforms = defaultValue(technique.uniforms, instanceProgram.uniforms);
- technique.states = defaultValue(technique.states, pass.states);
- }
- delete technique.passes;
- delete technique.pass;
- }
+}
+
+function removeTechniquePasses(gltf) {
+ var techniques = gltf.techniques;
+ for (var techniqueId in techniques) {
+ if (Object.prototype.hasOwnProperty.call(techniques, techniqueId)) {
+ var technique = techniques[techniqueId];
+ var passes = technique.passes;
+ if (defined(passes)) {
+ var passName = defaultValue(technique.pass, 'defaultPass');
+ if (Object.prototype.hasOwnProperty.call(passes, passName)) {
+ var pass = passes[passName];
+ var instanceProgram = pass.instanceProgram;
+ technique.attributes = defaultValue(technique.attributes, instanceProgram.attributes);
+ technique.program = defaultValue(technique.program, instanceProgram.program);
+ technique.uniforms = defaultValue(technique.uniforms, instanceProgram.uniforms);
+ technique.states = defaultValue(technique.states, pass.states);
+ }
+ delete technique.passes;
+ delete technique.pass;
}
}
}
+}
- function glTF08to10(gltf) {
- if (!defined(gltf.asset)) {
- gltf.asset = {};
- }
- var asset = gltf.asset;
- asset.version = '1.0';
- // Profile should be an object, not a string
- if (typeof asset.profile === 'string') {
- var split = asset.profile.split(' ');
- asset.profile = {
- api: split[0],
- version: split[1]
- };
- } else {
- asset.profile = {};
- }
-
- // Version property should be in asset, not on the root element
- if (defined(gltf.version)) {
- delete gltf.version;
- }
- // material.instanceTechnique properties should be directly on the material
- updateInstanceTechniques(gltf);
- // primitive.primitive should be primitive.mode
- setPrimitiveModes(gltf);
- // Node rotation should be quaternion, not axis-angle
- // node.instanceSkin is deprecated
- updateNodes(gltf);
- // Animations that target rotations should be quaternion, not axis-angle
- updateAnimations(gltf);
- // technique.pass and techniques.passes are deprecated
- removeTechniquePasses(gltf);
- // gltf.allExtensions -> extensionsUsed
- if (defined(gltf.allExtensions)) {
- gltf.extensionsUsed = gltf.allExtensions;
- delete gltf.allExtensions;
- }
- // gltf.lights -> khrMaterialsCommon.lights
- if (defined(gltf.lights)) {
- var extensions = defaultValue(gltf.extensions, {});
- gltf.extensions = extensions;
- var materialsCommon = defaultValue(extensions.KHR_materials_common, {});
- extensions.KHR_materials_common = materialsCommon;
- materialsCommon.lights = gltf.lights;
- delete gltf.lights;
- addExtensionsUsed(gltf, 'KHR_materials_common');
- }
+function glTF08to10(gltf) {
+ if (!defined(gltf.asset)) {
+ gltf.asset = {};
+ }
+ var asset = gltf.asset;
+ asset.version = '1.0';
+ // Profile should be an object, not a string
+ if (typeof asset.profile === 'string') {
+ var split = asset.profile.split(' ');
+ asset.profile = {
+ api: split[0],
+ version: split[1]
+ };
+ } else {
+ asset.profile = {};
}
- function removeAnimationSamplersIndirection(gltf) {
- var animations = gltf.animations;
- for (var animationId in animations) {
- if (Object.prototype.hasOwnProperty.call(animations, animationId)) {
- var animation = animations[animationId];
- var parameters = animation.parameters;
- if (defined(parameters)) {
- var samplers = animation.samplers;
- for (var samplerId in samplers) {
- if (Object.prototype.hasOwnProperty.call(samplers, samplerId)) {
- var sampler = samplers[samplerId];
- sampler.input = parameters[sampler.input];
- sampler.output = parameters[sampler.output];
- }
+ // Version property should be in asset, not on the root element
+ if (defined(gltf.version)) {
+ delete gltf.version;
+ }
+ // material.instanceTechnique properties should be directly on the material
+ updateInstanceTechniques(gltf);
+ // primitive.primitive should be primitive.mode
+ setPrimitiveModes(gltf);
+ // Node rotation should be quaternion, not axis-angle
+ // node.instanceSkin is deprecated
+ updateNodes(gltf);
+ // Animations that target rotations should be quaternion, not axis-angle
+ updateAnimations(gltf);
+ // technique.pass and techniques.passes are deprecated
+ removeTechniquePasses(gltf);
+ // gltf.allExtensions -> extensionsUsed
+ if (defined(gltf.allExtensions)) {
+ gltf.extensionsUsed = gltf.allExtensions;
+ delete gltf.allExtensions;
+ }
+ // gltf.lights -> khrMaterialsCommon.lights
+ if (defined(gltf.lights)) {
+ var extensions = defaultValue(gltf.extensions, {});
+ gltf.extensions = extensions;
+ var materialsCommon = defaultValue(extensions.KHR_materials_common, {});
+ extensions.KHR_materials_common = materialsCommon;
+ materialsCommon.lights = gltf.lights;
+ delete gltf.lights;
+ addExtensionsUsed(gltf, 'KHR_materials_common');
+ }
+}
+
+function removeAnimationSamplersIndirection(gltf) {
+ var animations = gltf.animations;
+ for (var animationId in animations) {
+ if (Object.prototype.hasOwnProperty.call(animations, animationId)) {
+ var animation = animations[animationId];
+ var parameters = animation.parameters;
+ if (defined(parameters)) {
+ var samplers = animation.samplers;
+ for (var samplerId in samplers) {
+ if (Object.prototype.hasOwnProperty.call(samplers, samplerId)) {
+ var sampler = samplers[samplerId];
+ sampler.input = parameters[sampler.input];
+ sampler.output = parameters[sampler.output];
}
- delete animation.parameters;
}
+ delete animation.parameters;
}
}
}
-
- function objectToArray(object, mapping) {
- var array = [];
- for (var id in object) {
- if (Object.prototype.hasOwnProperty.call(object, id)) {
- var value = object[id];
- mapping[id] = array.length;
- array.push(value);
- if (!defined(value.name)) {
- value.name = id;
- }
+}
+
+function objectToArray(object, mapping) {
+ var array = [];
+ for (var id in object) {
+ if (Object.prototype.hasOwnProperty.call(object, id)) {
+ var value = object[id];
+ mapping[id] = array.length;
+ array.push(value);
+ if (!defined(value.name)) {
+ value.name = id;
}
}
- return array;
}
+ return array;
+}
+
+function objectsToArrays(gltf) {
+ var i;
+ var globalMapping = {
+ accessors: {},
+ animations: {},
+ buffers: {},
+ bufferViews: {},
+ cameras: {},
+ images: {},
+ materials: {},
+ meshes: {},
+ nodes: {},
+ programs: {},
+ samplers: {},
+ scenes: {},
+ shaders: {},
+ skins: {},
+ textures: {},
+ techniques: {}
+ };
- function objectsToArrays(gltf) {
- var i;
- var globalMapping = {
- accessors: {},
- animations: {},
- buffers: {},
- bufferViews: {},
- cameras: {},
- images: {},
- materials: {},
- meshes: {},
- nodes: {},
- programs: {},
- samplers: {},
- scenes: {},
- shaders: {},
- skins: {},
- textures: {},
- techniques: {}
- };
-
- // Map joint names to id names
- var jointName;
- var jointNameToId = {};
- var nodes = gltf.nodes;
- for (var id in nodes) {
- if (Object.prototype.hasOwnProperty.call(nodes, id)) {
- jointName = nodes[id].jointName;
- if (defined(jointName)) {
- jointNameToId[jointName] = id;
- }
+ // Map joint names to id names
+ var jointName;
+ var jointNameToId = {};
+ var nodes = gltf.nodes;
+ for (var id in nodes) {
+ if (Object.prototype.hasOwnProperty.call(nodes, id)) {
+ jointName = nodes[id].jointName;
+ if (defined(jointName)) {
+ jointNameToId[jointName] = id;
}
}
+ }
- // Convert top level objects to arrays
- for (var topLevelId in gltf) {
- if (Object.prototype.hasOwnProperty.call(gltf, topLevelId) && defined(globalMapping[topLevelId])) {
- var objectMapping = {};
- var object = gltf[topLevelId];
- gltf[topLevelId] = objectToArray(object, objectMapping);
- globalMapping[topLevelId] = objectMapping;
- }
+ // Convert top level objects to arrays
+ for (var topLevelId in gltf) {
+ if (Object.prototype.hasOwnProperty.call(gltf, topLevelId) && defined(globalMapping[topLevelId])) {
+ var objectMapping = {};
+ var object = gltf[topLevelId];
+ gltf[topLevelId] = objectToArray(object, objectMapping);
+ globalMapping[topLevelId] = objectMapping;
}
+ }
- // Remap joint names to array indexes
- for (jointName in jointNameToId) {
- if (Object.prototype.hasOwnProperty.call(jointNameToId, jointName)) {
- jointNameToId[jointName] = globalMapping.nodes[jointNameToId[jointName]];
- }
+ // Remap joint names to array indexes
+ for (jointName in jointNameToId) {
+ if (Object.prototype.hasOwnProperty.call(jointNameToId, jointName)) {
+ jointNameToId[jointName] = globalMapping.nodes[jointNameToId[jointName]];
}
+ }
- // Fix references
- if (defined(gltf.scene)) {
- gltf.scene = globalMapping.scenes[gltf.scene];
+ // Fix references
+ if (defined(gltf.scene)) {
+ gltf.scene = globalMapping.scenes[gltf.scene];
+ }
+ ForEach.bufferView(gltf, function(bufferView) {
+ if (defined(bufferView.buffer)) {
+ bufferView.buffer = globalMapping.buffers[bufferView.buffer];
}
- ForEach.bufferView(gltf, function(bufferView) {
- if (defined(bufferView.buffer)) {
- bufferView.buffer = globalMapping.buffers[bufferView.buffer];
- }
- });
- ForEach.accessor(gltf, function(accessor) {
- if (defined(accessor.bufferView)) {
- accessor.bufferView = globalMapping.bufferViews[accessor.bufferView];
- }
- });
- ForEach.shader(gltf, function(shader) {
- var extensions = shader.extensions;
- if (defined(extensions)) {
- var binaryGltf = extensions.KHR_binary_glTF;
- if (defined(binaryGltf)) {
- shader.bufferView = globalMapping.bufferViews[binaryGltf.bufferView];
- delete extensions.KHR_binary_glTF;
- }
- if (Object.keys(extensions).length === 0) {
- delete shader.extensions;
- }
+ });
+ ForEach.accessor(gltf, function(accessor) {
+ if (defined(accessor.bufferView)) {
+ accessor.bufferView = globalMapping.bufferViews[accessor.bufferView];
+ }
+ });
+ ForEach.shader(gltf, function(shader) {
+ var extensions = shader.extensions;
+ if (defined(extensions)) {
+ var binaryGltf = extensions.KHR_binary_glTF;
+ if (defined(binaryGltf)) {
+ shader.bufferView = globalMapping.bufferViews[binaryGltf.bufferView];
+ delete extensions.KHR_binary_glTF;
+ }
+ if (Object.keys(extensions).length === 0) {
+ delete shader.extensions;
}
- });
- ForEach.program(gltf, function(program) {
- if (defined(program.vertexShader)) {
- program.vertexShader = globalMapping.shaders[program.vertexShader];
+ }
+ });
+ ForEach.program(gltf, function(program) {
+ if (defined(program.vertexShader)) {
+ program.vertexShader = globalMapping.shaders[program.vertexShader];
+ }
+ if (defined(program.fragmentShader)) {
+ program.fragmentShader = globalMapping.shaders[program.fragmentShader];
+ }
+ });
+ ForEach.technique(gltf, function(technique) {
+ if (defined(technique.program)) {
+ technique.program = globalMapping.programs[technique.program];
+ }
+ ForEach.techniqueParameter(technique, function(parameter) {
+ if (defined(parameter.node)) {
+ parameter.node = globalMapping.nodes[parameter.node];
}
- if (defined(program.fragmentShader)) {
- program.fragmentShader = globalMapping.shaders[program.fragmentShader];
+ var value = parameter.value;
+ if (typeof value === 'string') {
+ parameter.value = {
+ index: globalMapping.textures[value]
+ };
}
});
- ForEach.technique(gltf, function(technique) {
- if (defined(technique.program)) {
- technique.program = globalMapping.programs[technique.program];
+ });
+ ForEach.mesh(gltf, function(mesh) {
+ ForEach.meshPrimitive(mesh, function(primitive) {
+ if (defined(primitive.indices)) {
+ primitive.indices = globalMapping.accessors[primitive.indices];
}
- ForEach.techniqueParameter(technique, function(parameter) {
- if (defined(parameter.node)) {
- parameter.node = globalMapping.nodes[parameter.node];
- }
- var value = parameter.value;
- if (typeof value === 'string') {
- parameter.value = {
- index: globalMapping.textures[value]
- };
- }
- });
- });
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- if (defined(primitive.indices)) {
- primitive.indices = globalMapping.accessors[primitive.indices];
- }
- ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) {
- primitive.attributes[semantic] = globalMapping.accessors[accessorId];
- });
- if (defined(primitive.material)) {
- primitive.material = globalMapping.materials[primitive.material];
- }
+ ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) {
+ primitive.attributes[semantic] = globalMapping.accessors[accessorId];
});
- });
- ForEach.node(gltf, function(node) {
- var children = node.children;
- if (defined(children)) {
- var childrenLength = children.length;
- for (i = 0; i < childrenLength; ++i) {
- children[i] = globalMapping.nodes[children[i]];
- }
- }
- if (defined(node.meshes)) {
- // Split out meshes on nodes
- var meshes = node.meshes;
- var meshesLength = meshes.length;
- if (meshesLength > 0) {
- node.mesh = globalMapping.meshes[meshes[0]];
- for (i = 1; i < meshesLength; ++i) {
- var meshNode = {
- mesh: globalMapping.meshes[meshes[i]]
- };
- var meshNodeId = addToArray(gltf.nodes, meshNode);
- if (!defined(children)) {
- children = [];
- node.children = children;
- }
- children.push(meshNodeId);
- }
- }
- delete node.meshes;
- }
- if (defined(node.camera)) {
- node.camera = globalMapping.cameras[node.camera];
- }
- if (defined(node.skin)) {
- node.skin = globalMapping.skins[node.skin];
- }
- if (defined(node.skeletons)) {
- // Assign skeletons to skins
- var skeletons = node.skeletons;
- var skeletonsLength = skeletons.length;
- if ((skeletonsLength > 0) && defined(node.skin)) {
- var skin = gltf.skins[node.skin];
- skin.skeleton = globalMapping.nodes[skeletons[0]];
- }
- delete node.skeletons;
- }
- if (defined(node.jointName)) {
- delete node.jointName;
- }
- });
- ForEach.skin(gltf, function(skin) {
- if (defined(skin.inverseBindMatrices)) {
- skin.inverseBindMatrices = globalMapping.accessors[skin.inverseBindMatrices];
- }
- var jointNames = skin.jointNames;
- if (defined(jointNames)) {
- var joints = [];
- var jointNamesLength = jointNames.length;
- for (i = 0; i < jointNamesLength; ++i) {
- joints[i] = jointNameToId[jointNames[i]];
- }
- skin.joints = joints;
- delete skin.jointNames;
+ if (defined(primitive.material)) {
+ primitive.material = globalMapping.materials[primitive.material];
}
});
- ForEach.scene(gltf, function(scene) {
- var sceneNodes = scene.nodes;
- if (defined(sceneNodes)) {
- var sceneNodesLength = sceneNodes.length;
- for (i = 0; i < sceneNodesLength; ++i) {
- sceneNodes[i] = globalMapping.nodes[sceneNodes[i]];
- }
+ });
+ ForEach.node(gltf, function(node) {
+ var children = node.children;
+ if (defined(children)) {
+ var childrenLength = children.length;
+ for (i = 0; i < childrenLength; ++i) {
+ children[i] = globalMapping.nodes[children[i]];
}
- });
- ForEach.animation(gltf, function(animation) {
- var samplerMapping = {};
- animation.samplers = objectToArray(animation.samplers, samplerMapping);
- ForEach.animationSampler(animation, function(sampler) {
- sampler.input = globalMapping.accessors[sampler.input];
- sampler.output = globalMapping.accessors[sampler.output];
- });
- ForEach.animationChannel(animation, function(channel) {
- channel.sampler = samplerMapping[channel.sampler];
- var target = channel.target;
- if (defined(target)) {
- target.node = globalMapping.nodes[target.id];
- delete target.id;
- }
- });
- });
- ForEach.material(gltf, function(material) {
- if (defined(material.technique)) {
- material.technique = globalMapping.techniques[material.technique];
- }
- ForEach.materialValue(material, function(value, name) {
- if (typeof value === 'string') {
- material.values[name] = {
- index: globalMapping.textures[value]
+ }
+ if (defined(node.meshes)) {
+ // Split out meshes on nodes
+ var meshes = node.meshes;
+ var meshesLength = meshes.length;
+ if (meshesLength > 0) {
+ node.mesh = globalMapping.meshes[meshes[0]];
+ for (i = 1; i < meshesLength; ++i) {
+ var meshNode = {
+ mesh: globalMapping.meshes[meshes[i]]
};
- }
- });
- var extensions = material.extensions;
- if (defined(extensions)) {
- var materialsCommon = extensions.KHR_materials_common;
- if (defined(materialsCommon)) {
- ForEach.materialValue(materialsCommon, function(value, name) {
- if (typeof value === 'string') {
- materialsCommon.values[name] = {
- index: globalMapping.textures[value]
- };
- }
- });
+ var meshNodeId = addToArray(gltf.nodes, meshNode);
+ if (!defined(children)) {
+ children = [];
+ node.children = children;
+ }
+ children.push(meshNodeId);
}
}
- });
- ForEach.image(gltf, function(image) {
- var extensions = image.extensions;
- if (defined(extensions)) {
- var binaryGltf = extensions.KHR_binary_glTF;
- if (defined(binaryGltf)) {
- image.bufferView = globalMapping.bufferViews[binaryGltf.bufferView];
- image.mimeType = binaryGltf.mimeType;
- delete extensions.KHR_binary_glTF;
- }
- if (Object.keys(extensions).length === 0) {
- delete image.extensions;
- }
+ delete node.meshes;
+ }
+ if (defined(node.camera)) {
+ node.camera = globalMapping.cameras[node.camera];
+ }
+ if (defined(node.skin)) {
+ node.skin = globalMapping.skins[node.skin];
+ }
+ if (defined(node.skeletons)) {
+ // Assign skeletons to skins
+ var skeletons = node.skeletons;
+ var skeletonsLength = skeletons.length;
+ if ((skeletonsLength > 0) && defined(node.skin)) {
+ var skin = gltf.skins[node.skin];
+ skin.skeleton = globalMapping.nodes[skeletons[0]];
+ }
+ delete node.skeletons;
+ }
+ if (defined(node.jointName)) {
+ delete node.jointName;
+ }
+ });
+ ForEach.skin(gltf, function(skin) {
+ if (defined(skin.inverseBindMatrices)) {
+ skin.inverseBindMatrices = globalMapping.accessors[skin.inverseBindMatrices];
+ }
+ var jointNames = skin.jointNames;
+ if (defined(jointNames)) {
+ var joints = [];
+ var jointNamesLength = jointNames.length;
+ for (i = 0; i < jointNamesLength; ++i) {
+ joints[i] = jointNameToId[jointNames[i]];
+ }
+ skin.joints = joints;
+ delete skin.jointNames;
+ }
+ });
+ ForEach.scene(gltf, function(scene) {
+ var sceneNodes = scene.nodes;
+ if (defined(sceneNodes)) {
+ var sceneNodesLength = sceneNodes.length;
+ for (i = 0; i < sceneNodesLength; ++i) {
+ sceneNodes[i] = globalMapping.nodes[sceneNodes[i]];
}
- ForEach.compressedImage(image, function(compressedImage) {
- var compressedExtensions = compressedImage.extensions;
- if (defined(compressedExtensions)) {
- var compressedBinaryGltf = compressedExtensions.KHR_binary_glTF;
- if (defined(compressedBinaryGltf)) {
- compressedImage.bufferView = globalMapping.bufferViews[compressedBinaryGltf.bufferView];
- compressedImage.mimeType = compressedBinaryGltf.mimeType;
- delete compressedExtensions.KHR_binary_glTF;
- }
- if (Object.keys(extensions).length === 0) {
- delete compressedImage.extensions;
+ }
+ });
+ ForEach.animation(gltf, function(animation) {
+ var samplerMapping = {};
+ animation.samplers = objectToArray(animation.samplers, samplerMapping);
+ ForEach.animationSampler(animation, function(sampler) {
+ sampler.input = globalMapping.accessors[sampler.input];
+ sampler.output = globalMapping.accessors[sampler.output];
+ });
+ ForEach.animationChannel(animation, function(channel) {
+ channel.sampler = samplerMapping[channel.sampler];
+ var target = channel.target;
+ if (defined(target)) {
+ target.node = globalMapping.nodes[target.id];
+ delete target.id;
+ }
+ });
+ });
+ ForEach.material(gltf, function(material) {
+ if (defined(material.technique)) {
+ material.technique = globalMapping.techniques[material.technique];
+ }
+ ForEach.materialValue(material, function(value, name) {
+ if (typeof value === 'string') {
+ material.values[name] = {
+ index: globalMapping.textures[value]
+ };
+ }
+ });
+ var extensions = material.extensions;
+ if (defined(extensions)) {
+ var materialsCommon = extensions.KHR_materials_common;
+ if (defined(materialsCommon)) {
+ ForEach.materialValue(materialsCommon, function(value, name) {
+ if (typeof value === 'string') {
+ materialsCommon.values[name] = {
+ index: globalMapping.textures[value]
+ };
}
- }
- });
- });
- ForEach.texture(gltf, function(texture) {
- if (defined(texture.sampler)) {
- texture.sampler = globalMapping.samplers[texture.sampler];
+ });
}
- if (defined(texture.source)) {
- texture.source = globalMapping.images[texture.source];
+ }
+ });
+ ForEach.image(gltf, function(image) {
+ var extensions = image.extensions;
+ if (defined(extensions)) {
+ var binaryGltf = extensions.KHR_binary_glTF;
+ if (defined(binaryGltf)) {
+ image.bufferView = globalMapping.bufferViews[binaryGltf.bufferView];
+ image.mimeType = binaryGltf.mimeType;
+ delete extensions.KHR_binary_glTF;
+ }
+ if (Object.keys(extensions).length === 0) {
+ delete image.extensions;
}
- });
- }
+ }
+ });
+ ForEach.texture(gltf, function(texture) {
+ if (defined(texture.sampler)) {
+ texture.sampler = globalMapping.samplers[texture.sampler];
+ }
+ if (defined(texture.source)) {
+ texture.source = globalMapping.images[texture.source];
+ }
+ });
+}
- function removeAnimationSamplerNames(gltf) {
- ForEach.animation(gltf, function(animation) {
- ForEach.animationSampler(animation, function(sampler) {
- delete sampler.name;
- });
+function removeAnimationSamplerNames(gltf) {
+ ForEach.animation(gltf, function(animation) {
+ ForEach.animationSampler(animation, function(sampler) {
+ delete sampler.name;
});
- }
+ });
+}
- function removeEmptyArrays(gltf) {
- for (var topLevelId in gltf) {
- if (Object.prototype.hasOwnProperty.call(gltf, topLevelId)) {
- var array = gltf[topLevelId];
- if (Array.isArray(array) && array.length === 0) {
- delete gltf[topLevelId];
- }
+function removeEmptyArrays(gltf) {
+ for (var topLevelId in gltf) {
+ if (Object.prototype.hasOwnProperty.call(gltf, topLevelId)) {
+ var array = gltf[topLevelId];
+ if (Array.isArray(array) && array.length === 0) {
+ delete gltf[topLevelId];
}
}
- ForEach.node(gltf, function(node) {
- if (defined(node.children) && node.children.length === 0) {
- delete node.children;
- }
- });
- }
-
- function stripAsset(gltf) {
- var asset = gltf.asset;
- delete asset.profile;
- delete asset.premultipliedAlpha;
}
-
- var knownExtensions = {
- CESIUM_RTC: true,
- KHR_materials_common: true,
- WEB3D_quantized_attributes: true
- };
- function requireKnownExtensions(gltf) {
- var extensionsUsed = gltf.extensionsUsed;
- gltf.extensionsRequired = defaultValue(gltf.extensionsRequired, []);
- if (defined(extensionsUsed)) {
- var extensionsUsedLength = extensionsUsed.length;
- for (var i = 0; i < extensionsUsedLength; ++i) {
- var extension = extensionsUsed[i];
- if (defined(knownExtensions[extension])) {
- gltf.extensionsRequired.push(extension);
- }
+ ForEach.node(gltf, function(node) {
+ if (defined(node.children) && node.children.length === 0) {
+ delete node.children;
+ }
+ });
+}
+
+function stripAsset(gltf) {
+ var asset = gltf.asset;
+ delete asset.profile;
+ delete asset.premultipliedAlpha;
+}
+
+var knownExtensions = {
+ CESIUM_RTC: true,
+ KHR_materials_common: true,
+ WEB3D_quantized_attributes: true
+};
+function requireKnownExtensions(gltf) {
+ var extensionsUsed = gltf.extensionsUsed;
+ gltf.extensionsRequired = defaultValue(gltf.extensionsRequired, []);
+ if (defined(extensionsUsed)) {
+ var extensionsUsedLength = extensionsUsed.length;
+ for (var i = 0; i < extensionsUsedLength; ++i) {
+ var extension = extensionsUsed[i];
+ if (defined(knownExtensions[extension])) {
+ gltf.extensionsRequired.push(extension);
}
}
}
-
- function removeBufferType(gltf) {
- ForEach.buffer(gltf, function(buffer) {
- delete buffer.type;
- });
- }
-
- function removeTextureProperties(gltf) {
- ForEach.texture(gltf, function(texture) {
- delete texture.format;
- delete texture.internalFormat;
- delete texture.target;
- delete texture.type;
- });
- }
-
- function requireAttributeSetIndex(gltf) {
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) {
- if (semantic === 'TEXCOORD') {
- primitive.attributes.TEXCOORD_0 = accessorId;
- } else if (semantic === 'COLOR') {
- primitive.attributes.COLOR_0 = accessorId;
- }
- });
- delete primitive.attributes.TEXCOORD;
- delete primitive.attributes.COLOR;
- });
- });
- ForEach.technique(gltf, function(technique) {
- ForEach.techniqueParameter(technique, function(parameter) {
- var semantic = parameter.semantic;
- if (defined(semantic)) {
- if (semantic === 'TEXCOORD') {
- parameter.semantic = 'TEXCOORD_0';
- } else if (semantic === 'COLOR') {
- parameter.semantic = 'COLOR_0';
- }
+}
+
+function removeBufferType(gltf) {
+ ForEach.buffer(gltf, function(buffer) {
+ delete buffer.type;
+ });
+}
+
+function removeTextureProperties(gltf) {
+ ForEach.texture(gltf, function(texture) {
+ delete texture.format;
+ delete texture.internalFormat;
+ delete texture.target;
+ delete texture.type;
+ });
+}
+
+function requireAttributeSetIndex(gltf) {
+ ForEach.mesh(gltf, function(mesh) {
+ ForEach.meshPrimitive(mesh, function(primitive) {
+ ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) {
+ if (semantic === 'TEXCOORD') {
+ primitive.attributes.TEXCOORD_0 = accessorId;
+ } else if (semantic === 'COLOR') {
+ primitive.attributes.COLOR_0 = accessorId;
}
});
- });
- }
-
- var knownSemantics = {
- POSITION: true,
- NORMAL: true,
- TANGENT: true
- };
- var indexedSemantics = {
- COLOR: 'COLOR',
- JOINT : 'JOINTS',
- JOINTS: 'JOINTS',
- TEXCOORD: 'TEXCOORD',
- WEIGHT: 'WEIGHTS',
- WEIGHTS: 'WEIGHTS'
- };
- function underscoreApplicationSpecificSemantics(gltf) {
- var mappedSemantics = {};
- ForEach.mesh(gltf, function(mesh) {
- ForEach.meshPrimitive(mesh, function(primitive) {
- /*eslint-disable no-unused-vars*/
- ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) {
- if (semantic.charAt(0) !== '_') {
- var setIndex = semantic.search(/_[0-9]+/g);
- var strippedSemantic = semantic;
- var suffix = '_0';
- if (setIndex >= 0) {
- strippedSemantic = semantic.substring(0, setIndex);
- suffix = semantic.substring(setIndex);
- }
- var newSemantic;
- var indexedSemantic = indexedSemantics[strippedSemantic];
- if (defined(indexedSemantic)) {
- newSemantic = indexedSemantic + suffix;
- mappedSemantics[semantic] = newSemantic;
- } else if (!defined(knownSemantics[strippedSemantic])) {
- newSemantic = '_' + semantic;
- mappedSemantics[semantic] = newSemantic;
- }
+ delete primitive.attributes.TEXCOORD;
+ delete primitive.attributes.COLOR;
+ });
+ });
+ ForEach.technique(gltf, function(technique) {
+ ForEach.techniqueParameter(technique, function(parameter) {
+ var semantic = parameter.semantic;
+ if (defined(semantic)) {
+ if (semantic === 'TEXCOORD') {
+ parameter.semantic = 'TEXCOORD_0';
+ } else if (semantic === 'COLOR') {
+ parameter.semantic = 'COLOR_0';
+ }
+ }
+ });
+ });
+}
+
+var knownSemantics = {
+ POSITION: true,
+ NORMAL: true,
+ TANGENT: true
+};
+var indexedSemantics = {
+ COLOR: 'COLOR',
+ JOINT : 'JOINTS',
+ JOINTS: 'JOINTS',
+ TEXCOORD: 'TEXCOORD',
+ WEIGHT: 'WEIGHTS',
+ WEIGHTS: 'WEIGHTS'
+};
+function underscoreApplicationSpecificSemantics(gltf) {
+ var mappedSemantics = {};
+ ForEach.mesh(gltf, function(mesh) {
+ ForEach.meshPrimitive(mesh, function(primitive) {
+ /*eslint-disable no-unused-vars*/
+ ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) {
+ if (semantic.charAt(0) !== '_') {
+ var setIndex = semantic.search(/_[0-9]+/g);
+ var strippedSemantic = semantic;
+ var suffix = '_0';
+ if (setIndex >= 0) {
+ strippedSemantic = semantic.substring(0, setIndex);
+ suffix = semantic.substring(setIndex);
}
- });
- for (var semantic in mappedSemantics) {
- if (Object.prototype.hasOwnProperty.call(mappedSemantics, semantic)) {
- var mappedSemantic = mappedSemantics[semantic];
- var accessorId = primitive.attributes[semantic];
- if (defined(accessorId)) {
- delete primitive.attributes[semantic];
- primitive.attributes[mappedSemantic] = accessorId;
- }
+ var newSemantic;
+ var indexedSemantic = indexedSemantics[strippedSemantic];
+ if (defined(indexedSemantic)) {
+ newSemantic = indexedSemantic + suffix;
+ mappedSemantics[semantic] = newSemantic;
+ } else if (!defined(knownSemantics[strippedSemantic])) {
+ newSemantic = '_' + semantic;
+ mappedSemantics[semantic] = newSemantic;
}
}
});
- });
- ForEach.technique(gltf, function(technique) {
- ForEach.techniqueParameter(technique, function(parameter) {
- var mappedSemantic = mappedSemantics[parameter.semantic];
- if (defined(mappedSemantic)) {
- parameter.semantic = mappedSemantic;
- }
- });
- });
- }
-
- function clampCameraParameters(gltf) {
- ForEach.camera(gltf, function(camera) {
- var perspective = camera.perspective;
- if (defined(perspective)) {
- var aspectRatio = perspective.aspectRatio;
- if (defined(aspectRatio) && aspectRatio === 0.0) {
- delete perspective.aspectRatio;
- }
- var yfov = perspective.yfov;
- if (defined(yfov) && yfov === 0.0) {
- perspective.yfov = 1.0;
+ for (var semantic in mappedSemantics) {
+ if (Object.prototype.hasOwnProperty.call(mappedSemantics, semantic)) {
+ var mappedSemantic = mappedSemantics[semantic];
+ var accessorId = primitive.attributes[semantic];
+ if (defined(accessorId)) {
+ delete primitive.attributes[semantic];
+ primitive.attributes[mappedSemantic] = accessorId;
+ }
}
}
});
- }
-
- function computeAccessorByteStride(gltf, accessor) {
- return (defined(accessor.byteStride) && accessor.byteStride !== 0) ? accessor.byteStride : getAccessorByteStride(gltf, accessor);
- }
-
- function requireByteLength(gltf) {
- ForEach.buffer(gltf, function(buffer) {
- if (!defined(buffer.byteLength)) {
- buffer.byteLength = buffer.extras._pipeline.source.length;
+ });
+ ForEach.technique(gltf, function(technique) {
+ ForEach.techniqueParameter(technique, function(parameter) {
+ var mappedSemantic = mappedSemantics[parameter.semantic];
+ if (defined(mappedSemantic)) {
+ parameter.semantic = mappedSemantic;
}
});
- ForEach.accessor(gltf, function(accessor) {
- var bufferViewId = accessor.bufferView;
- if (defined(bufferViewId)) {
- var bufferView = gltf.bufferViews[bufferViewId];
- var accessorByteStride = computeAccessorByteStride(gltf, accessor);
- var accessorByteEnd = accessor.byteOffset + accessor.count * accessorByteStride;
- bufferView.byteLength = Math.max(defaultValue(bufferView.byteLength, 0), accessorByteEnd);
- }
- });
- }
+ });
+}
- function moveByteStrideToBufferView(gltf) {
- var i;
- var j;
- var bufferView;
- var bufferViews = gltf.bufferViews;
-
- var bufferViewHasVertexAttributes = {};
- ForEach.accessorContainingVertexAttributeData(gltf, function(accessorId) {
- var accessor = gltf.accessors[accessorId];
- if (defined(accessor.bufferView)) {
- bufferViewHasVertexAttributes[accessor.bufferView] = true;
+function clampCameraParameters(gltf) {
+ ForEach.camera(gltf, function(camera) {
+ var perspective = camera.perspective;
+ if (defined(perspective)) {
+ var aspectRatio = perspective.aspectRatio;
+ if (defined(aspectRatio) && aspectRatio === 0.0) {
+ delete perspective.aspectRatio;
}
- });
-
- // Map buffer views to a list of accessors
- var bufferViewMap = {};
- ForEach.accessor(gltf, function(accessor) {
- if (defined(accessor.bufferView)) {
- bufferViewMap[accessor.bufferView] = defaultValue(bufferViewMap[accessor.bufferView], []);
- bufferViewMap[accessor.bufferView].push(accessor);
+ var yfov = perspective.yfov;
+ if (defined(yfov) && yfov === 0.0) {
+ perspective.yfov = 1.0;
}
- });
+ }
+ });
+}
- // Split accessors with different byte strides
- for (var bufferViewId in bufferViewMap) {
- if (Object.prototype.hasOwnProperty.call(bufferViewMap, bufferViewId)) {
- bufferView = bufferViews[bufferViewId];
- var accessors = bufferViewMap[bufferViewId];
- accessors.sort(function(a, b) {
- return a.byteOffset - b.byteOffset;
- });
- var currentByteOffset = 0;
- var currentIndex = 0;
- var accessorsLength = accessors.length;
- for (i = 0; i < accessorsLength; ++i) {
- var accessor = accessors[i];
- var accessorByteStride = computeAccessorByteStride(gltf, accessor);
- var accessorByteOffset = accessor.byteOffset;
- var accessorByteLength = accessor.count * accessorByteStride;
- delete accessor.byteStride;
-
- var hasNextAccessor = (i < accessorsLength - 1);
- var nextAccessorByteStride = hasNextAccessor ? computeAccessorByteStride(gltf, accessors[i + 1]) : undefined;
- if (accessorByteStride !== nextAccessorByteStride) {
- var newBufferView = clone(bufferView, true);
- if (bufferViewHasVertexAttributes[bufferViewId]) {
- newBufferView.byteStride = accessorByteStride;
- }
- newBufferView.byteOffset += currentByteOffset;
- newBufferView.byteLength = accessorByteOffset + accessorByteLength - currentByteOffset;
- var newBufferViewId = addToArray(bufferViews, newBufferView);
- for (j = currentIndex; j <= i; ++j) {
- accessor = accessors[j];
- accessor.bufferView = newBufferViewId;
- accessor.byteOffset = accessor.byteOffset - currentByteOffset;
- }
- // Set current byte offset to next accessor's byte offset
- currentByteOffset = hasNextAccessor ? accessors[i + 1].byteOffset : undefined;
- currentIndex = i + 1;
+function computeAccessorByteStride(gltf, accessor) {
+ return (defined(accessor.byteStride) && accessor.byteStride !== 0) ? accessor.byteStride : getAccessorByteStride(gltf, accessor);
+}
+
+function requireByteLength(gltf) {
+ ForEach.buffer(gltf, function(buffer) {
+ if (!defined(buffer.byteLength)) {
+ buffer.byteLength = buffer.extras._pipeline.source.length;
+ }
+ });
+ ForEach.accessor(gltf, function(accessor) {
+ var bufferViewId = accessor.bufferView;
+ if (defined(bufferViewId)) {
+ var bufferView = gltf.bufferViews[bufferViewId];
+ var accessorByteStride = computeAccessorByteStride(gltf, accessor);
+ var accessorByteEnd = accessor.byteOffset + accessor.count * accessorByteStride;
+ bufferView.byteLength = Math.max(defaultValue(bufferView.byteLength, 0), accessorByteEnd);
+ }
+ });
+}
+
+function moveByteStrideToBufferView(gltf) {
+ var i;
+ var j;
+ var bufferView;
+ var bufferViews = gltf.bufferViews;
+
+ var bufferViewHasVertexAttributes = {};
+ ForEach.accessorContainingVertexAttributeData(gltf, function(accessorId) {
+ var accessor = gltf.accessors[accessorId];
+ if (defined(accessor.bufferView)) {
+ bufferViewHasVertexAttributes[accessor.bufferView] = true;
+ }
+ });
+
+ // Map buffer views to a list of accessors
+ var bufferViewMap = {};
+ ForEach.accessor(gltf, function(accessor) {
+ if (defined(accessor.bufferView)) {
+ bufferViewMap[accessor.bufferView] = defaultValue(bufferViewMap[accessor.bufferView], []);
+ bufferViewMap[accessor.bufferView].push(accessor);
+ }
+ });
+
+ // Split accessors with different byte strides
+ for (var bufferViewId in bufferViewMap) {
+ if (Object.prototype.hasOwnProperty.call(bufferViewMap, bufferViewId)) {
+ bufferView = bufferViews[bufferViewId];
+ var accessors = bufferViewMap[bufferViewId];
+ accessors.sort(function(a, b) {
+ return a.byteOffset - b.byteOffset;
+ });
+ var currentByteOffset = 0;
+ var currentIndex = 0;
+ var accessorsLength = accessors.length;
+ for (i = 0; i < accessorsLength; ++i) {
+ var accessor = accessors[i];
+ var accessorByteStride = computeAccessorByteStride(gltf, accessor);
+ var accessorByteOffset = accessor.byteOffset;
+ var accessorByteLength = accessor.count * accessorByteStride;
+ delete accessor.byteStride;
+
+ var hasNextAccessor = (i < accessorsLength - 1);
+ var nextAccessorByteStride = hasNextAccessor ? computeAccessorByteStride(gltf, accessors[i + 1]) : undefined;
+ if (accessorByteStride !== nextAccessorByteStride) {
+ var newBufferView = clone(bufferView, true);
+ if (bufferViewHasVertexAttributes[bufferViewId]) {
+ newBufferView.byteStride = accessorByteStride;
}
+ newBufferView.byteOffset += currentByteOffset;
+ newBufferView.byteLength = accessorByteOffset + accessorByteLength - currentByteOffset;
+ var newBufferViewId = addToArray(bufferViews, newBufferView);
+ for (j = currentIndex; j <= i; ++j) {
+ accessor = accessors[j];
+ accessor.bufferView = newBufferViewId;
+ accessor.byteOffset = accessor.byteOffset - currentByteOffset;
+ }
+ // Set current byte offset to next accessor's byte offset
+ currentByteOffset = hasNextAccessor ? accessors[i + 1].byteOffset : undefined;
+ currentIndex = i + 1;
}
}
}
-
- // Remove unused buffer views
- removeUnusedElements(gltf, ['accessor', 'bufferView', 'buffer']);
- }
-
- function requirePositionAccessorMinMax(gltf) {
- ForEach.accessorWithSemantic(gltf, 'POSITION', function(accessorId) {
- var accessor = gltf.accessors[accessorId];
- if (!defined(accessor.min) || !defined(accessor.max)) {
- var minMax = findAccessorMinMax(gltf, accessor);
- accessor.min = minMax.min;
- accessor.max = minMax.max;
- }
- });
- }
-
- function isNodeEmpty(node) {
- return (!defined(node.children) || node.children.length === 0) &&
- (!defined(node.meshes) || node.meshes.length === 0) &&
- !defined(node.camera) && !defined(node.skin) && !defined(node.skeletons) && !defined(node.jointName) &&
- (!defined(node.translation) || Cartesian3.fromArray(node.translation).equals(Cartesian3.ZERO)) &&
- (!defined(node.scale) || Cartesian3.fromArray(node.scale).equals(new Cartesian3(1.0, 1.0, 1.0))) &&
- (!defined(node.rotation) || Cartesian4.fromArray(node.rotation).equals(new Cartesian4(0.0, 0.0, 0.0, 1.0))) &&
- (!defined(node.matrix) || Matrix4.fromColumnMajorArray(node.matrix).equals(Matrix4.IDENTITY)) &&
- !defined(node.extensions) && !defined(node.extras);
}
- function deleteNode(gltf, nodeId) {
- // Remove from list of nodes in scene
- ForEach.scene(gltf, function(scene) {
- var sceneNodes = scene.nodes;
- if (defined(sceneNodes)) {
- var sceneNodesLength = sceneNodes.length;
- for (var i = sceneNodesLength; i >= 0; --i) {
- if (sceneNodes[i] === nodeId) {
- sceneNodes.splice(i, 1);
- return;
- }
+ // Remove unused buffer views
+ removeUnusedElements(gltf, ['accessor', 'bufferView', 'buffer']);
+}
+
+function requirePositionAccessorMinMax(gltf) {
+ ForEach.accessorWithSemantic(gltf, 'POSITION', function(accessorId) {
+ var accessor = gltf.accessors[accessorId];
+ if (!defined(accessor.min) || !defined(accessor.max)) {
+ var minMax = findAccessorMinMax(gltf, accessor);
+ accessor.min = minMax.min;
+ accessor.max = minMax.max;
+ }
+ });
+}
+
+function isNodeEmpty(node) {
+ return (!defined(node.children) || node.children.length === 0) &&
+ (!defined(node.meshes) || node.meshes.length === 0) &&
+ !defined(node.camera) && !defined(node.skin) && !defined(node.skeletons) && !defined(node.jointName) &&
+ (!defined(node.translation) || Cartesian3.fromArray(node.translation).equals(Cartesian3.ZERO)) &&
+ (!defined(node.scale) || Cartesian3.fromArray(node.scale).equals(new Cartesian3(1.0, 1.0, 1.0))) &&
+ (!defined(node.rotation) || Cartesian4.fromArray(node.rotation).equals(new Cartesian4(0.0, 0.0, 0.0, 1.0))) &&
+ (!defined(node.matrix) || Matrix4.fromColumnMajorArray(node.matrix).equals(Matrix4.IDENTITY)) &&
+ !defined(node.extensions) && !defined(node.extras);
+}
+
+function deleteNode(gltf, nodeId) {
+ // Remove from list of nodes in scene
+ ForEach.scene(gltf, function(scene) {
+ var sceneNodes = scene.nodes;
+ if (defined(sceneNodes)) {
+ var sceneNodesLength = sceneNodes.length;
+ for (var i = sceneNodesLength; i >= 0; --i) {
+ if (sceneNodes[i] === nodeId) {
+ sceneNodes.splice(i, 1);
+ return;
}
}
- });
+ }
+ });
- // Remove parent node's reference to this node, and delete the parent if also empty
- ForEach.node(gltf, function(parentNode, parentNodeId) {
- if (defined(parentNode.children)) {
- var index = parentNode.children.indexOf(nodeId);
- if (index > -1) {
- parentNode.children.splice(index, 1);
+ // Remove parent node's reference to this node, and delete the parent if also empty
+ ForEach.node(gltf, function(parentNode, parentNodeId) {
+ if (defined(parentNode.children)) {
+ var index = parentNode.children.indexOf(nodeId);
+ if (index > -1) {
+ parentNode.children.splice(index, 1);
- if (isNodeEmpty(parentNode)) {
- deleteNode(gltf, parentNodeId);
- }
+ if (isNodeEmpty(parentNode)) {
+ deleteNode(gltf, parentNodeId);
}
}
- });
+ }
+ });
- delete gltf.nodes[nodeId];
- }
+ delete gltf.nodes[nodeId];
+}
- function removeEmptyNodes(gltf) {
- ForEach.node(gltf, function(node, nodeId) {
- if (isNodeEmpty(node)) {
- deleteNode(gltf, nodeId);
- }
- });
+function removeEmptyNodes(gltf) {
+ ForEach.node(gltf, function(node, nodeId) {
+ if (isNodeEmpty(node)) {
+ deleteNode(gltf, nodeId);
+ }
+ });
- return gltf;
- }
+ return gltf;
+}
- function requireAnimationAccessorMinMax(gltf) {
- ForEach.animation(gltf, function(animation) {
- ForEach.animationSampler(animation, function(sampler) {
- var accessor = gltf.accessors[sampler.input];
- if (!defined(accessor.min) || !defined(accessor.max)) {
- var minMax = findAccessorMinMax(gltf, accessor);
- accessor.min = minMax.min;
- accessor.max = minMax.max;
- }
- });
+function requireAnimationAccessorMinMax(gltf) {
+ ForEach.animation(gltf, function(animation) {
+ ForEach.animationSampler(animation, function(sampler) {
+ var accessor = gltf.accessors[sampler.input];
+ if (!defined(accessor.min) || !defined(accessor.max)) {
+ var minMax = findAccessorMinMax(gltf, accessor);
+ accessor.min = minMax.min;
+ accessor.max = minMax.max;
+ }
});
- }
-
- function glTF10to20(gltf) {
- gltf.asset = defaultValue(gltf.asset, {});
- gltf.asset.version = '2.0';
- // material.instanceTechnique properties should be directly on the material. instanceTechnique is a gltf 0.8 property but is seen in some 1.0 models.
- updateInstanceTechniques(gltf);
- // animation.samplers now refers directly to accessors and animation.parameters should be removed
- removeAnimationSamplersIndirection(gltf);
- // Remove empty nodes and re-assign referencing indices
- removeEmptyNodes(gltf);
- // Top-level objects are now arrays referenced by index instead of id
- objectsToArrays(gltf);
- // Animation.sampler objects cannot have names
- removeAnimationSamplerNames(gltf);
- // asset.profile no longer exists
- stripAsset(gltf);
- // Move known extensions from extensionsUsed to extensionsRequired
- requireKnownExtensions(gltf);
- // bufferView.byteLength and buffer.byteLength are required
- requireByteLength(gltf);
- // byteStride moved from accessor to bufferView
- moveByteStrideToBufferView(gltf);
- // accessor.min and accessor.max must be defined for accessors containing POSITION attributes
- requirePositionAccessorMinMax(gltf);
- // An animation sampler's input accessor must have min and max properties defined
- requireAnimationAccessorMinMax(gltf);
- // buffer.type is unnecessary and should be removed
- removeBufferType(gltf);
- // Remove format, internalFormat, target, and type
- removeTextureProperties(gltf);
- // TEXCOORD and COLOR attributes must be written with a set index (TEXCOORD_#)
- requireAttributeSetIndex(gltf);
- // Add underscores to application-specific parameters
- underscoreApplicationSpecificSemantics(gltf);
- // Accessors referenced by JOINTS_0 and WEIGHTS_0 attributes must have correct component types
- updateAccessorComponentTypes(gltf);
- // Clamp camera parameters
- clampCameraParameters(gltf);
- // Move legacy technique render states to material properties and add KHR_blend extension blending functions
- moveTechniqueRenderStates(gltf);
- // Add material techniques to KHR_techniques_webgl extension, removing shaders, programs, and techniques
- moveTechniquesToExtension(gltf);
- // Remove empty arrays
- removeEmptyArrays(gltf);
- }
-
- export default updateVersion;
+ });
+}
+
+function glTF10to20(gltf) {
+ gltf.asset = defaultValue(gltf.asset, {});
+ gltf.asset.version = '2.0';
+ // material.instanceTechnique properties should be directly on the material. instanceTechnique is a gltf 0.8 property but is seen in some 1.0 models.
+ updateInstanceTechniques(gltf);
+ // animation.samplers now refers directly to accessors and animation.parameters should be removed
+ removeAnimationSamplersIndirection(gltf);
+ // Remove empty nodes and re-assign referencing indices
+ removeEmptyNodes(gltf);
+ // Top-level objects are now arrays referenced by index instead of id
+ objectsToArrays(gltf);
+ // Animation.sampler objects cannot have names
+ removeAnimationSamplerNames(gltf);
+ // asset.profile no longer exists
+ stripAsset(gltf);
+ // Move known extensions from extensionsUsed to extensionsRequired
+ requireKnownExtensions(gltf);
+ // bufferView.byteLength and buffer.byteLength are required
+ requireByteLength(gltf);
+ // byteStride moved from accessor to bufferView
+ moveByteStrideToBufferView(gltf);
+ // accessor.min and accessor.max must be defined for accessors containing POSITION attributes
+ requirePositionAccessorMinMax(gltf);
+ // An animation sampler's input accessor must have min and max properties defined
+ requireAnimationAccessorMinMax(gltf);
+ // buffer.type is unnecessary and should be removed
+ removeBufferType(gltf);
+ // Remove format, internalFormat, target, and type
+ removeTextureProperties(gltf);
+ // TEXCOORD and COLOR attributes must be written with a set index (TEXCOORD_#)
+ requireAttributeSetIndex(gltf);
+ // Add underscores to application-specific parameters
+ underscoreApplicationSpecificSemantics(gltf);
+ // Accessors referenced by JOINTS_0 and WEIGHTS_0 attributes must have correct component types
+ updateAccessorComponentTypes(gltf);
+ // Clamp camera parameters
+ clampCameraParameters(gltf);
+ // Move legacy technique render states to material properties and add KHR_blend extension blending functions
+ moveTechniqueRenderStates(gltf);
+ // Add material techniques to KHR_techniques_webgl extension, removing shaders, programs, and techniques
+ moveTechniquesToExtension(gltf);
+ // Remove empty arrays
+ removeEmptyArrays(gltf);
+}
+
+export default updateVersion;
diff --git a/Source/ThirdParty/GltfPipeline/usesExtension.js b/Source/ThirdParty/GltfPipeline/usesExtension.js
index c3726f0941cc..545e03725d50 100644
--- a/Source/ThirdParty/GltfPipeline/usesExtension.js
+++ b/Source/ThirdParty/GltfPipeline/usesExtension.js
@@ -1,16 +1,16 @@
-import defined from '../../Core/defined.js'
+import defined from "../../Core/defined.js"
- /**
- * Checks whether the glTF uses the given extension.
- *
- * @param {Object} gltf A javascript object containing a glTF asset.
- * @param {String} extension The name of the extension.
- * @returns {Boolean} Whether the glTF uses the given extension.
- *
- * @private
- */
- function usesExtension(gltf, extension) {
- return defined(gltf.extensionsUsed) && (gltf.extensionsUsed.indexOf(extension) >= 0);
- }
+/**
+ * Checks whether the glTF uses the given extension.
+ *
+ * @param {Object} gltf A javascript object containing a glTF asset.
+ * @param {String} extension The name of the extension.
+ * @returns {Boolean} Whether the glTF uses the given extension.
+ *
+ * @private
+ */
+function usesExtension(gltf, extension) {
+ return defined(gltf.extensionsUsed) && (gltf.extensionsUsed.indexOf(extension) >= 0);
+}
- export default usesExtension;
+export default usesExtension;
diff --git a/Source/ThirdParty/Workers/basis_transcoder.js b/Source/ThirdParty/Workers/basis_transcoder.js
new file mode 100644
index 000000000000..7ad429d4a9a6
--- /dev/null
+++ b/Source/ThirdParty/Workers/basis_transcoder.js
@@ -0,0 +1,21 @@
+
+var BASIS = (function() {
+ var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
+ if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;
+ return (
+function(BASIS) {
+ BASIS = BASIS || {};
+
+var Module=typeof BASIS!=="undefined"?BASIS:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseRejectza=reject});var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)}}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!=="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!=="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heap[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>>0&((t|0)!=(-1|0)&(q|0)!=(-1|0))^1)):0){h=s?r:b;g=t;v=135}if((v|0)==135){b=(f[1252]|0)+h|0;f[1252]=b;if(b>>>0>(f[1253]|0)>>>0)f[1253]=b;j=f[1150]|0;do if(j){b=5024;while(1){a=f[b>>2]|0;c=b+4|0;d=f[c>>2]|0;if((g|0)==(a+d|0)){v=145;break}e=f[b+8>>2]|0;if(!e)break;else b=e}if(((v|0)==145?(f[b+12>>2]&8|0)==0:0)?j>>>0>>0&j>>>0>=a>>>0:0){f[c>>2]=d+h;w=j+8|0;w=(w&7|0)==0?0:0-w&7;v=j+w|0;w=(f[1147]|0)+(h-w)|0;f[1150]=v;f[1147]=w;f[v+4>>2]=w|1;f[v+w+4>>2]=40;f[1151]=f[1266];break}if(g>>>0<(f[1148]|0)>>>0)f[1148]=g;c=g+h|0;b=5024;while(1){if((f[b>>2]|0)==(c|0)){v=153;break}a=f[b+8>>2]|0;if(!a)break;else b=a}if((v|0)==153?(f[b+12>>2]&8|0)==0:0){f[b>>2]=g;l=b+4|0;f[l>>2]=(f[l>>2]|0)+h;l=g+8|0;l=g+((l&7|0)==0?0:0-l&7)|0;b=c+8|0;b=c+((b&7|0)==0?0:0-b&7)|0;k=l+m|0;i=b-l-m|0;f[l+4>>2]=m|3;do if((b|0)!=(j|0)){if((b|0)==(f[1149]|0)){w=(f[1146]|0)+i|0;f[1146]=w;f[1149]=k;f[k+4>>2]=w|1;f[k+w>>2]=w;break}a=f[b+4>>2]|0;if((a&3|0)==1){h=a&-8;d=a>>>3;d:do if(a>>>0<256){a=f[b+8>>2]|0;c=f[b+12>>2]|0;if((c|0)==(a|0)){f[1144]=f[1144]&~(1< >2]=c;f[c+8>>2]=a;break}}else{g=f[b+24>>2]|0;a=f[b+12>>2]|0;do if((a|0)==(b|0)){d=b+16|0;c=d+4|0;a=f[c>>2]|0;if(!a){a=f[d>>2]|0;if(!a){a=0;break}else c=d}while(1){d=a+20|0;e=f[d>>2]|0;if(e|0){a=e;c=d;continue}d=a+16|0;e=f[d>>2]|0;if(!e)break;else{a=e;c=d}}f[c>>2]=0}else{w=f[b+8>>2]|0;f[w+12>>2]=a;f[a+8>>2]=w}while(0);if(!g)break;c=f[b+28>>2]|0;d=4880+(c<<2)|0;do if((b|0)!=(f[d>>2]|0)){f[g+16+(((f[g+16>>2]|0)!=(b|0)&1)<<2)>>2]=a;if(!a)break d}else{f[d>>2]=a;if(a|0)break;f[1145]=f[1145]&~(1< >2]=g;c=b+16|0;d=f[c>>2]|0;if(d|0){f[a+16>>2]=d;f[d+24>>2]=a}c=f[c+4>>2]|0;if(!c)break;f[a+20>>2]=c;f[c+24>>2]=a}while(0);b=b+h|0;e=h+i|0}else e=i;b=b+4|0;f[b>>2]=f[b>>2]&-2;f[k+4>>2]=e|1;f[k+e>>2]=e;b=e>>>3;if(e>>>0<256){c=4616+(b<<1<<2)|0;a=f[1144]|0;b=1<>2]|0}f[a>>2]=k;f[b+12>>2]=k;f[k+8>>2]=b;f[k+12>>2]=c;break}b=e>>>8;do if(!b)b=0;else{if(e>>>0>16777215){b=31;break}v=(b+1048320|0)>>>16&8;w=b< >>16&4;w=w< >>16&2;b=14-(t|v|b)+(w<>>15)|0;b=e>>>(b+7|0)&1|b<<1}while(0);d=4880+(b<<2)|0;f[k+28>>2]=b;a=k+16|0;f[a+4>>2]=0;f[a>>2]=0;a=f[1145]|0;c=1<>2]=k;f[k+24>>2]=d;f[k+12>>2]=k;f[k+8>>2]=k;break}a=e<<((b|0)==31?0:25-(b>>>1)|0);c=f[d>>2]|0;while(1){if((f[c+4>>2]&-8|0)==(e|0)){v=194;break}d=c+16+(a>>>31<<2)|0;b=f[d>>2]|0;if(!b){v=193;break}else{a=a<<1;c=b}}if((v|0)==193){f[d>>2]=k;f[k+24>>2]=c;f[k+12>>2]=k;f[k+8>>2]=k;break}else if((v|0)==194){v=c+8|0;w=f[v>>2]|0;f[w+12>>2]=k;f[v>>2]=k;f[k+8>>2]=w;f[k+12>>2]=c;f[k+24>>2]=0;break}}else{w=(f[1147]|0)+i|0;f[1147]=w;f[1150]=k;f[k+4>>2]=w|1}while(0);w=l+8|0;u=x;return w|0}b=5024;while(1){a=f[b>>2]|0;if(a>>>0<=j>>>0?(w=a+(f[b+4>>2]|0)|0,w>>>0>j>>>0):0)break;b=f[b+8>>2]|0}e=w+-47|0;a=e+8|0;a=e+((a&7|0)==0?0:0-a&7)|0;e=j+16|0;a=a>>>0 >>0?j:a;b=a+8|0;c=g+8|0;c=(c&7|0)==0?0:0-c&7;v=g+c|0;c=h+-40-c|0;f[1150]=v;f[1147]=c;f[v+4>>2]=c|1;f[v+c+4>>2]=40;f[1151]=f[1266];c=a+4|0;f[c>>2]=27;f[b>>2]=f[1256];f[b+4>>2]=f[1257];f[b+8>>2]=f[1258];f[b+12>>2]=f[1259];f[1256]=g;f[1257]=h;f[1259]=0;f[1258]=b;b=a+24|0;do{v=b;b=b+4|0;f[b>>2]=7}while((v+8|0)>>>0 >>0);if((a|0)!=(j|0)){g=a-j|0;f[c>>2]=f[c>>2]&-2;f[j+4>>2]=g|1;f[a>>2]=g;b=g>>>3;if(g>>>0<256){c=4616+(b<<1<<2)|0;a=f[1144]|0;b=1<>2]|0}f[a>>2]=j;f[b+12>>2]=j;f[j+8>>2]=b;f[j+12>>2]=c;break}b=g>>>8;if(b)if(g>>>0>16777215)c=31;else{v=(b+1048320|0)>>>16&8;w=b< >>16&4;w=w< >>16&2;c=14-(t|v|c)+(w< >>15)|0;c=g>>>(c+7|0)&1|c<<1}else c=0;d=4880+(c<<2)|0;f[j+28>>2]=c;f[j+20>>2]=0;f[e>>2]=0;b=f[1145]|0;a=1< >2]=j;f[j+24>>2]=d;f[j+12>>2]=j;f[j+8>>2]=j;break}a=g<<((c|0)==31?0:25-(c>>>1)|0);c=f[d>>2]|0;while(1){if((f[c+4>>2]&-8|0)==(g|0)){v=216;break}d=c+16+(a>>>31<<2)|0;b=f[d>>2]|0;if(!b){v=215;break}else{a=a<<1;c=b}}if((v|0)==215){f[d>>2]=j;f[j+24>>2]=c;f[j+12>>2]=j;f[j+8>>2]=j;break}else if((v|0)==216){v=c+8|0;w=f[v>>2]|0;f[w+12>>2]=j;f[v>>2]=j;f[j+8>>2]=w;f[j+12>>2]=c;f[j+24>>2]=0;break}}}else{w=f[1148]|0;if((w|0)==0|g>>>0 >>0)f[1148]=g;f[1256]=g;f[1257]=h;f[1259]=0;f[1153]=f[1262];f[1152]=-1;b=0;do{w=4616+(b<<1<<2)|0;f[w+12>>2]=w;f[w+8>>2]=w;b=b+1|0}while((b|0)!=32);w=g+8|0;w=(w&7|0)==0?0:0-w&7;v=g+w|0;w=h+-40-w|0;f[1150]=v;f[1147]=w;f[v+4>>2]=w|1;f[v+w+4>>2]=40;f[1151]=f[1266]}while(0);b=f[1147]|0;if(b>>>0>m>>>0){t=b-m|0;f[1147]=t;w=f[1150]|0;v=w+m|0;f[1150]=v;f[v+4>>2]=t|1;f[w+4>>2]=m|3;w=w+8|0;u=x;return w|0}}w=jd()|0;f[w>>2]=12;w=0;u=x;return w|0}function Na(a,c,d,e,g,i){a=a|0;c=+c;d=d|0;e=e|0;g=g|0;i=i|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0.0,r=0,s=0,t=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0;G=u;u=u+560|0;l=G+8|0;t=G;F=G+524|0;E=F;m=G+512|0;f[t>>2]=0;D=m+12|0;Fc(c)|0;if((I|0)<0){c=-c;B=1;A=2087}else{B=(g&2049|0)!=0&1;A=(g&2048|0)==0?((g&1|0)==0?2088:2093):2090}Fc(c)|0;C=I&2146435072;do if(C>>>0<2146435072|(C|0)==2146435072&0<0){q=+hd(c,t)*2.0;j=q!=0.0;if(j)f[t>>2]=(f[t>>2]|0)+-1;w=i|32;if((w|0)==97){r=i&32;p=(r|0)==0?A:A+9|0;o=B|2;j=12-e|0;do if(!(e>>>0>11|(j|0)==0)){c=8.0;do{j=j+-1|0;c=c*16.0}while((j|0)!=0);if((b[p>>0]|0)==45){c=-(c+(-q-c));break}else{c=q+c-c;break}}else c=q;while(0);k=f[t>>2]|0;j=(k|0)<0?0-k|0:k;j=Rb(j,((j|0)<0)<<31>>31,D)|0;if((j|0)==(D|0)){j=m+11|0;b[j>>0]=48}b[j+-1>>0]=(k>>31&2)+43;n=j+-2|0;b[n>>0]=i+15;m=(e|0)<1;l=(g&8|0)==0;j=F;do{C=~~c;k=j+1|0;b[j>>0]=h[2122+C>>0]|r;c=(c-+(C|0))*16.0;if((k-E|0)==1?!(l&(m&c==0.0)):0){b[k>>0]=46;j=j+2|0}else j=k}while(c!=0.0);C=j-E|0;E=D-n|0;D=(e|0)!=0&(C+-2|0)<(e|0)?e+2|0:C;j=E+o+D|0;Wb(a,32,d,j,g);Nc(a,p,o);Wb(a,48,d,j,g^65536);Nc(a,F,C);Wb(a,48,D-C|0,0,0);Nc(a,n,E);Wb(a,32,d,j,g^8192);break}k=(e|0)<0?6:e;if(j){j=(f[t>>2]|0)+-28|0;f[t>>2]=j;c=q*268435456.0}else{c=q;j=f[t>>2]|0}C=(j|0)<0?l:l+288|0;l=C;do{y=~~c>>>0;f[l>>2]=y;l=l+4|0;c=(c-+(y>>>0))*1.0e9}while(c!=0.0);if((j|0)>0){m=C;o=l;while(1){n=(j|0)<29?j:29;j=o+-4|0;if(j>>>0>=m>>>0){l=0;do{x=yc(f[j>>2]|0,0,n|0)|0;x=Gc(x|0,I|0,l|0,0)|0;y=I;v=mc(x|0,y|0,1e9,0)|0;f[j>>2]=v;l=Uc(x|0,y|0,1e9,0)|0;j=j+-4|0}while(j>>>0>=m>>>0);if(l){m=m+-4|0;f[m>>2]=l}}l=o;while(1){if(l>>>0<=m>>>0)break;j=l+-4|0;if(!(f[j>>2]|0))l=j;else break}j=(f[t>>2]|0)-n|0;f[t>>2]=j;if((j|0)>0)o=l;else break}}else m=C;if((j|0)<0){e=((k+25|0)/9|0)+1|0;s=(w|0)==102;do{r=0-j|0;r=(r|0)<9?r:9;if(m>>>0 >>0){n=(1< >>r;p=0;j=m;do{y=f[j>>2]|0;f[j>>2]=(y>>>r)+p;p=X(y&n,o)|0;j=j+4|0}while(j>>>0 >>0);j=(f[m>>2]|0)==0?m+4|0:m;if(!p){m=j;j=l}else{f[l>>2]=p;m=j;j=l+4|0}}else{m=(f[m>>2]|0)==0?m+4|0:m;j=l}l=s?C:m;l=(j-l>>2|0)>(e|0)?l+(e<<2)|0:j;j=(f[t>>2]|0)+r|0;f[t>>2]=j}while((j|0)<0);j=m;e=l}else{j=m;e=l}y=C;if(j>>>0 >>0){l=(y-j>>2)*9|0;n=f[j>>2]|0;if(n>>>0>=10){m=10;do{m=m*10|0;l=l+1|0}while(n>>>0>=m>>>0)}}else l=0;s=(w|0)==103;v=(k|0)!=0;m=k-((w|0)!=102?l:0)+((v&s)<<31>>31)|0;if((m|0)<(((e-y>>2)*9|0)+-9|0)){m=m+9216|0;r=C+4+(((m|0)/9|0)+-1024<<2)|0;m=((m|0)%9|0)+1|0;if((m|0)<9){n=10;do{n=n*10|0;m=m+1|0}while((m|0)!=9)}else n=10;o=f[r>>2]|0;p=(o>>>0)%(n>>>0)|0;m=(r+4|0)==(e|0);if(!(m&(p|0)==0)){q=(((o>>>0)/(n>>>0)|0)&1|0)==0?9007199254740992.0:9007199254740994.0;x=(n|0)/2|0;c=p>>>0 >>0?.5:m&(p|0)==(x|0)?1.0:1.5;if(B){x=(b[A>>0]|0)==45;c=x?-c:c;q=x?-q:q}m=o-p|0;f[r>>2]=m;if(q+c!=q){x=m+n|0;f[r>>2]=x;if(x>>>0>999999999){l=r;while(1){m=l+-4|0;f[l>>2]=0;if(m>>>0 >>0){j=j+-4|0;f[j>>2]=0}x=(f[m>>2]|0)+1|0;f[m>>2]=x;if(x>>>0>999999999)l=m;else break}}else m=r;l=(y-j>>2)*9|0;o=f[j>>2]|0;if(o>>>0>=10){n=10;do{n=n*10|0;l=l+1|0}while(o>>>0>=n>>>0)}}else m=r}else m=r;m=m+4|0;m=e>>>0>m>>>0?m:e;x=j}else{m=e;x=j}w=m;while(1){if(w>>>0<=x>>>0){t=0;break}j=w+-4|0;if(!(f[j>>2]|0))w=j;else{t=1;break}}e=0-l|0;do if(s){j=((v^1)&1)+k|0;if((j|0)>(l|0)&(l|0)>-5){n=i+-1|0;k=j+-1-l|0}else{n=i+-2|0;k=j+-1|0}j=g&8;if(!j){if(t?(z=f[w+-4>>2]|0,(z|0)!=0):0)if(!((z>>>0)%10|0)){m=0;j=10;do{j=j*10|0;m=m+1|0}while(!((z>>>0)%(j>>>0)|0|0))}else m=0;else m=9;j=((w-y>>2)*9|0)+-9|0;if((n|32|0)==102){r=j-m|0;r=(r|0)>0?r:0;k=(k|0)<(r|0)?k:r;r=0;break}else{r=j+l-m|0;r=(r|0)>0?r:0;k=(k|0)<(r|0)?k:r;r=0;break}}else r=j}else{n=i;r=g&8}while(0);s=k|r;o=(s|0)!=0&1;p=(n|32|0)==102;if(p){v=0;j=(l|0)>0?l:0}else{j=(l|0)<0?e:l;j=Rb(j,((j|0)<0)<<31>>31,D)|0;m=D;if((m-j|0)<2)do{j=j+-1|0;b[j>>0]=48}while((m-j|0)<2);b[j+-1>>0]=(l>>31&2)+43;j=j+-2|0;b[j>>0]=n;v=j;j=m-j|0}j=B+1+k+o+j|0;Wb(a,32,d,j,g);Nc(a,A,B);Wb(a,48,d,j,g^65536);if(p){n=x>>>0>C>>>0?C:x;r=F+9|0;o=r;p=F+8|0;m=n;do{l=Rb(f[m>>2]|0,0,r)|0;if((m|0)==(n|0)){if((l|0)==(r|0)){b[p>>0]=48;l=p}}else if(l>>>0>F>>>0){Ib(F|0,48,l-E|0)|0;do l=l+-1|0;while(l>>>0>F>>>0)}Nc(a,l,o-l|0);m=m+4|0}while(m>>>0<=C>>>0);if(s|0)Nc(a,2138,1);if(m>>>0 >>0&(k|0)>0)while(1){l=Rb(f[m>>2]|0,0,r)|0;if(l>>>0>F>>>0){Ib(F|0,48,l-E|0)|0;do l=l+-1|0;while(l>>>0>F>>>0)}Nc(a,l,(k|0)<9?k:9);m=m+4|0;l=k+-9|0;if(!(m>>>0 >>0&(k|0)>9)){k=l;break}else k=l}Wb(a,48,k+9|0,9,0)}else{s=t?w:x+4|0;if((k|0)>-1){t=F+9|0;r=(r|0)==0;e=t;o=0-E|0;p=F+8|0;n=x;do{l=Rb(f[n>>2]|0,0,t)|0;if((l|0)==(t|0)){b[p>>0]=48;l=p}do if((n|0)==(x|0)){m=l+1|0;Nc(a,l,1);if(r&(k|0)<1){l=m;break}Nc(a,2138,1);l=m}else{if(l>>>0<=F>>>0)break;Ib(F|0,48,l+o|0)|0;do l=l+-1|0;while(l>>>0>F>>>0)}while(0);E=e-l|0;Nc(a,l,(k|0)>(E|0)?E:k);k=k-E|0;n=n+4|0}while(n>>>0 >>0&(k|0)>-1)}Wb(a,48,k+18|0,18,0);Nc(a,v,D-v|0)}Wb(a,32,d,j,g^8192)}else{F=(i&32|0)!=0;j=B+3|0;Wb(a,32,d,j,g&-65537);Nc(a,A,B);Nc(a,c!=c|0.0!=0.0?(F?2114:2118):F?2106:2110,3);Wb(a,32,d,j,g^8192)}while(0);u=G;return ((j|0)<(d|0)?d:j)|0}function Oa(a,c,e,g,h){a=a|0;c=c|0;e=e|0;g=g|0;h=h|0;var i=0,j=0,k=0,l=0,m=0,n=0,o=0,q=0,r=0,s=0,t=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0;G=u;u=u+64|0;C=G+16|0;D=G;A=G+24|0;E=G+8|0;F=G+20|0;f[C>>2]=c;x=(a|0)!=0;y=A+40|0;z=y;A=A+39|0;B=E+4|0;j=0;i=0;n=0;a:while(1){do if((i|0)>-1)if((j|0)>(2147483647-i|0)){i=jd()|0;f[i>>2]=75;i=-1;break}else{i=j+i|0;break}while(0);j=b[c>>0]|0;if(!(j<<24>>24)){w=87;break}else k=c;b:while(1){switch(j<<24>>24){case 37:{j=k;w=9;break b}case 0:{j=k;break b}default:{}}v=k+1|0;f[C>>2]=v;j=b[v>>0]|0;k=v}c:do if((w|0)==9)while(1){w=0;if((b[k+1>>0]|0)!=37)break c;j=j+1|0;k=k+2|0;f[C>>2]=k;if((b[k>>0]|0)==37)w=9;else break}while(0);j=j-c|0;if(x)Nc(a,c,j);if(j|0){c=k;continue}l=k+1|0;j=(b[l>>0]|0)+-48|0;if(j>>>0<10){v=(b[k+2>>0]|0)==36;t=v?j:-1;n=v?1:n;l=v?k+3|0:l}else t=-1;f[C>>2]=l;j=b[l>>0]|0;k=(j<<24>>24)+-32|0;d:do if(k>>>0<32){m=0;o=j;while(1){j=1<>2]=l;j=b[l>>0]|0;k=(j<<24>>24)+-32|0;if(k>>>0>=32)break;else o=j}}else m=0;while(0);if(j<<24>>24==42){k=l+1|0;j=(b[k>>0]|0)+-48|0;if(j>>>0<10?(b[l+2>>0]|0)==36:0){f[h+(j<<2)>>2]=10;j=f[g+((b[k>>0]|0)+-48<<3)>>2]|0;n=1;l=l+3|0}else{if(n|0){i=-1;break}if(x){n=(f[e>>2]|0)+(4-1)&~(4-1);j=f[n>>2]|0;f[e>>2]=n+4;n=0;l=k}else{j=0;n=0;l=k}}f[C>>2]=l;v=(j|0)<0;j=v?0-j|0:j;m=v?m|8192:m}else{j=ec(C)|0;if((j|0)<0){i=-1;break}l=f[C>>2]|0}do if((b[l>>0]|0)==46){if((b[l+1>>0]|0)!=42){f[C>>2]=l+1;k=ec(C)|0;l=f[C>>2]|0;break}o=l+2|0;k=(b[o>>0]|0)+-48|0;if(k>>>0<10?(b[l+3>>0]|0)==36:0){f[h+(k<<2)>>2]=10;k=f[g+((b[o>>0]|0)+-48<<3)>>2]|0;l=l+4|0;f[C>>2]=l;break}if(n|0){i=-1;break a}if(x){v=(f[e>>2]|0)+(4-1)&~(4-1);k=f[v>>2]|0;f[e>>2]=v+4}else k=0;f[C>>2]=o;l=o}else k=-1;while(0);s=0;while(1){if(((b[l>>0]|0)+-65|0)>>>0>57){i=-1;break a}v=l+1|0;f[C>>2]=v;o=b[(b[l>>0]|0)+-65+(1606+(s*58|0))>>0]|0;q=o&255;if((q+-1|0)>>>0<8){s=q;l=v}else break}if(!(o<<24>>24)){i=-1;break}r=(t|0)>-1;do if(o<<24>>24==19)if(r){i=-1;break a}else w=49;else{if(r){f[h+(t<<2)>>2]=q;r=g+(t<<3)|0;t=f[r+4>>2]|0;w=D;f[w>>2]=f[r>>2];f[w+4>>2]=t;w=49;break}if(!x){i=0;break a}db(D,q,e)}while(0);if((w|0)==49?(w=0,!x):0){j=0;c=v;continue}l=b[l>>0]|0;l=(s|0)!=0&(l&15|0)==3?l&-33:l;r=m&-65537;t=(m&8192|0)==0?m:r;e:do switch(l|0){case 110:switch((s&255)<<24>>24){case 0:{f[f[D>>2]>>2]=i;j=0;c=v;continue a}case 1:{f[f[D>>2]>>2]=i;j=0;c=v;continue a}case 2:{j=f[D>>2]|0;f[j>>2]=i;f[j+4>>2]=((i|0)<0)<<31>>31;j=0;c=v;continue a}case 3:{d[f[D>>2]>>1]=i;j=0;c=v;continue a}case 4:{b[f[D>>2]>>0]=i;j=0;c=v;continue a}case 6:{f[f[D>>2]>>2]=i;j=0;c=v;continue a}case 7:{j=f[D>>2]|0;f[j>>2]=i;f[j+4>>2]=((i|0)<0)<<31>>31;j=0;c=v;continue a}default:{j=0;c=v;continue a}}case 112:{l=120;k=k>>>0>8?k:8;c=t|8;w=61;break}case 88:case 120:{c=t;w=61;break}case 111:{l=D;c=f[l>>2]|0;l=f[l+4>>2]|0;q=kc(c,l,y)|0;r=z-q|0;m=0;o=2070;k=(t&8|0)==0|(k|0)>(r|0)?k:r+1|0;r=t;w=67;break}case 105:case 100:{l=D;c=f[l>>2]|0;l=f[l+4>>2]|0;if((l|0)<0){c=Cc(0,0,c|0,l|0)|0;l=I;m=D;f[m>>2]=c;f[m+4>>2]=l;m=1;o=2070;w=66;break e}else{m=(t&2049|0)!=0&1;o=(t&2048|0)==0?((t&1|0)==0?2070:2072):2071;w=66;break e}}case 117:{l=D;m=0;o=2070;c=f[l>>2]|0;l=f[l+4>>2]|0;w=66;break}case 99:{b[A>>0]=f[D>>2];c=A;m=0;o=2070;q=y;l=1;k=r;break}case 109:{l=jd()|0;l=Qc(f[l>>2]|0)|0;w=71;break}case 115:{l=f[D>>2]|0;l=l|0?l:2080;w=71;break}case 67:{f[E>>2]=f[D>>2];f[B>>2]=0;f[D>>2]=E;q=-1;l=E;w=75;break}case 83:{c=f[D>>2]|0;if(!k){Wb(a,32,j,0,t);c=0;w=84}else{q=k;l=c;w=75}break}case 65:case 71:case 70:case 69:case 97:case 103:case 102:case 101:{j=Na(a,+p[D>>3],j,k,t,l)|0;c=v;continue a}default:{m=0;o=2070;q=y;l=k;k=t}}while(0);f:do if((w|0)==61){t=D;s=f[t>>2]|0;t=f[t+4>>2]|0;q=gc(s,t,y,l&32)|0;o=(c&8|0)==0|(s|0)==0&(t|0)==0;m=o?0:2;o=o?2070:2070+(l>>4)|0;r=c;c=s;l=t;w=67}else if((w|0)==66){q=Rb(c,l,y)|0;r=t;w=67}else if((w|0)==71){w=0;t=vb(l,0,k)|0;s=(t|0)==0;c=l;m=0;o=2070;q=s?l+k|0:t;l=s?k:t-l|0;k=r}else if((w|0)==75){w=0;o=l;c=0;k=0;while(1){m=f[o>>2]|0;if(!m)break;k=Rc(F,m)|0;if((k|0)<0|k>>>0>(q-c|0)>>>0)break;c=k+c|0;if(q>>>0>c>>>0)o=o+4|0;else break}if((k|0)<0){i=-1;break a}Wb(a,32,j,c,t);if(!c){c=0;w=84}else{m=0;while(1){k=f[l>>2]|0;if(!k){w=84;break f}k=Rc(F,k)|0;m=k+m|0;if((m|0)>(c|0)){w=84;break f}Nc(a,F,k);if(m>>>0>=c>>>0){w=84;break}else l=l+4|0}}}while(0);if((w|0)==67){w=0;l=(c|0)!=0|(l|0)!=0;t=(k|0)!=0|l;l=((l^1)&1)+(z-q)|0;c=t?q:y;q=y;l=t?((k|0)>(l|0)?k:l):k;k=(k|0)>-1?r&-65537:r}else if((w|0)==84){w=0;Wb(a,32,j,c,t^8192);j=(j|0)>(c|0)?j:c;c=v;continue}s=q-c|0;r=(l|0)<(s|0)?s:l;t=r+m|0;j=(j|0)<(t|0)?t:j;Wb(a,32,j,t,k);Nc(a,o,m);Wb(a,48,j,t,k^65536);Wb(a,48,r,s,0);Nc(a,c,s);Wb(a,32,j,t,k^8192);c=v}g:do if((w|0)==87)if(!a)if(!n)i=0;else{i=1;while(1){c=f[h+(i<<2)>>2]|0;if(!c)break;db(g+(i<<3)|0,c,e);i=i+1|0;if((i|0)>=10){i=1;break g}}while(1){if(f[h+(i<<2)>>2]|0){i=-1;break g}i=i+1|0;if((i|0)>=10){i=1;break}}}while(0);u=G;return i|0}function Pa(a,c){a=a|0;c=c|0;var d=0,e=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0;E=u;u=u+704|0;A=E+144|0;z=E+128|0;y=E+112|0;x=E+96|0;w=E+80|0;v=E+64|0;t=E+48|0;B=E+32|0;n=E+16|0;k=E;p=E+184|0;D=E+160|0;q=yb(a,14)|0;if(!q){Eb(c);D=1;u=E;return D|0}r=c+4|0;s=c+8|0;d=f[s>>2]|0;if((d|0)!=(q|0)){if(d>>>0<=q>>>0){do if((f[c+12>>2]|0)>>>0 >>0){if(fb(r,q,(d+1|0)==(q|0),1,0)|0){d=f[s>>2]|0;break}b[c+16>>0]=1;D=0;u=E;return D|0}while(0);Ib((f[r>>2]|0)+d|0,0,q-d|0)|0}f[s>>2]=q}Ib(f[r>>2]|0,0,q|0)|0;o=a+20|0;d=f[o>>2]|0;if((d|0)<5){i=a+4|0;j=a+8|0;g=a+16|0;do{e=f[i>>2]|0;if((e|0)==(f[j>>2]|0))e=0;else{f[i>>2]=e+1;e=h[e>>0]|0}d=d+8|0;f[o>>2]=d;if((d|0)>=33){f[k>>2]=866;f[k+4>>2]=3208;f[k+8>>2]=1366;vc(p,812,k)|0;Ub(p)|0;d=f[o>>2]|0}e=e<<32-d|f[g>>2];f[g>>2]=e}while((d|0)<5)}else{e=a+16|0;g=e;e=f[e>>2]|0}m=e>>>27;f[g>>2]=e<<5;f[o>>2]=d+-5;if((m+-1|0)>>>0>20){D=0;u=E;return D|0}f[D+20>>2]=0;f[D>>2]=0;f[D+4>>2]=0;f[D+8>>2]=0;f[D+12>>2]=0;b[D+16>>0]=0;d=D+4|0;e=D+8|0;a:do if(fb(d,21,0,1,0)|0){i=f[e>>2]|0;l=f[d>>2]|0;Ib(l+i|0,0,21-i|0)|0;f[e>>2]=21;i=a+4|0;j=a+8|0;k=a+16|0;g=0;do{d=f[o>>2]|0;if((d|0)<3)do{e=f[i>>2]|0;if((e|0)==(f[j>>2]|0))e=0;else{f[i>>2]=e+1;e=h[e>>0]|0}d=d+8|0;f[o>>2]=d;if((d|0)>=33){f[n>>2]=866;f[n+4>>2]=3208;f[n+8>>2]=1366;vc(p,812,n)|0;Ub(p)|0;d=f[o>>2]|0}e=e<<32-d|f[k>>2];f[k>>2]=e}while((d|0)<3);else e=f[k>>2]|0;f[k>>2]=e<<3;f[o>>2]=d+-3;b[l+(h[1327+g>>0]|0)>>0]=e>>>29;g=g+1|0}while((g|0)!=(m|0));if(qb(D)|0){k=a+4|0;l=a+8|0;m=a+16|0;d=0;b:do{j=q-d|0;g=bb(a,D)|0;c:do if(g>>>0<17){if((f[s>>2]|0)>>>0<=d>>>0){f[B>>2]=866;f[B+4>>2]=910;f[B+8>>2]=1497;vc(p,812,B)|0;Ub(p)|0}b[(f[r>>2]|0)+d>>0]=g;d=d+1|0}else switch(g|0){case 17:{e=f[o>>2]|0;if((e|0)<3)do{g=f[k>>2]|0;if((g|0)==(f[l>>2]|0))g=0;else{f[k>>2]=g+1;g=h[g>>0]|0}e=e+8|0;f[o>>2]=e;if((e|0)>=33){f[t>>2]=866;f[t+4>>2]=3208;f[t+8>>2]=1366;vc(p,812,t)|0;Ub(p)|0;e=f[o>>2]|0}g=g<<32-e|f[m>>2];f[m>>2]=g}while((e|0)<3);else g=f[m>>2]|0;f[m>>2]=g<<3;f[o>>2]=e+-3;g=(g>>>29)+3|0;e=g>>>0>j>>>0;if(e){d=0;break a}else{d=(e?0:g)+d|0;break c}}case 18:{e=f[o>>2]|0;if((e|0)<7)do{g=f[k>>2]|0;if((g|0)==(f[l>>2]|0))g=0;else{f[k>>2]=g+1;g=h[g>>0]|0}e=e+8|0;f[o>>2]=e;if((e|0)>=33){f[v>>2]=866;f[v+4>>2]=3208;f[v+8>>2]=1366;vc(p,812,v)|0;Ub(p)|0;e=f[o>>2]|0}g=g<<32-e|f[m>>2];f[m>>2]=g}while((e|0)<7);else g=f[m>>2]|0;f[m>>2]=g<<7;f[o>>2]=e+-7;g=(g>>>25)+11|0;e=g>>>0>j>>>0;if(e){d=0;break a}else{d=(e?0:g)+d|0;break c}}default:{if((g+-19|0)>>>0>=2){C=81;break b}e=f[o>>2]|0;if((g|0)==19){if((e|0)<2){g=e;while(1){e=f[k>>2]|0;if((e|0)==(f[l>>2]|0))i=0;else{f[k>>2]=e+1;i=h[e>>0]|0}e=g+8|0;f[o>>2]=e;if((e|0)>=33){f[w>>2]=866;f[w+4>>2]=3208;f[w+8>>2]=1366;vc(p,812,w)|0;Ub(p)|0;e=f[o>>2]|0}g=i<<32-e|f[m>>2];f[m>>2]=g;if((e|0)<2)g=e;else break}}else g=f[m>>2]|0;f[m>>2]=g<<2;g=g>>>30;i=3;e=e+-2|0}else{if((e|0)<6)do{g=f[k>>2]|0;if((g|0)==(f[l>>2]|0))g=0;else{f[k>>2]=g+1;g=h[g>>0]|0}e=e+8|0;f[o>>2]=e;if((e|0)>=33){f[x>>2]=866;f[x+4>>2]=3208;f[x+8>>2]=1366;vc(p,812,x)|0;Ub(p)|0;e=f[o>>2]|0}g=g<<32-e|f[m>>2];f[m>>2]=g}while((e|0)<6);else g=f[m>>2]|0;f[m>>2]=g<<6;g=g>>>26;i=7;e=e+-6|0}f[o>>2]=e;g=g+i|0;if((d|0)==0|g>>>0>j>>>0){d=0;break a}e=d+-1|0;if((f[s>>2]|0)>>>0<=e>>>0){f[y>>2]=866;f[y+4>>2]=910;f[y+8>>2]=1497;vc(p,812,y)|0;Ub(p)|0}i=b[(f[r>>2]|0)+e>>0]|0;if(!(i<<24>>24)){d=0;break a}e=g+d|0;if(d>>>0>=e>>>0)break c;do{if((f[s>>2]|0)>>>0<=d>>>0){f[z>>2]=866;f[z+4>>2]=910;f[z+8>>2]=1497;vc(p,812,z)|0;Ub(p)|0}b[(f[r>>2]|0)+d>>0]=i;d=d+1|0}while((d|0)!=(e|0));d=e}}while(0)}while(q>>>0>d>>>0);if((C|0)==81){f[A>>2]=866;f[A+4>>2]=3149;f[A+8>>2]=1348;vc(p,812,A)|0;Ub(p)|0;d=0;break}if((q|0)==(d|0))d=qb(c)|0;else d=0}else d=0}else{b[D+16>>0]=1;d=0}while(0);Cb(D);D=d;u=E;return D|0}function Qa(a,c,e,g){a=a|0;c=c|0;e=e|0;g=g|0;var i=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0;L=u;u=u+880|0;J=L+144|0;I=L+128|0;H=L+112|0;G=L+96|0;C=L+80|0;x=L+64|0;v=L+48|0;w=L+32|0;q=L+16|0;p=L;E=L+360|0;F=L+296|0;K=L+224|0;t=L+156|0;if((c|0)==0|g>>>0>11){K=0;u=L;return K|0}f[a>>2]=c;i=K;k=i+68|0;do{f[i>>2]=0;i=i+4|0}while((i|0)<(k|0));i=0;do{D=b[e+i>>0]|0;k=K+((D&255)<<2)|0;if(D<<24>>24)f[k>>2]=(f[k>>2]|0)+1;i=i+1|0}while((i|0)!=(c|0));k=0;l=0;m=0;n=-1;o=1;while(1){i=f[K+(o<<2)>>2]|0;if(!i){f[a+28+(o+-1<<2)>>2]=0;r=l}else{r=o+-1|0;f[F+(r<<2)>>2]=k;k=i+k|0;D=16-o|0;f[a+28+(r<<2)>>2]=(k+-1<>2]=l;f[t+(o<<2)>>2]=l;r=i+l|0;m=m>>>0>o>>>0?m:o;n=n>>>0 >>0?n:o}o=o+1|0;if((o|0)==17)break;else{k=k<<1;l=r}}f[a+4>>2]=r;k=a+172|0;do if(r>>>0>(f[k>>2]|0)>>>0){i=r+-1|0;if(!(i&r))i=r;else{i=i>>>16|i;i=i>>>8|i;i=i>>>4|i;i=i>>>2|i;i=(i>>>1|i)+1|0;i=i>>>0>c>>>0?c:i}f[k>>2]=i;l=a+176|0;i=f[l>>2]|0;do if(i|0){D=f[i+-4>>2]|0;i=i+-8|0;if(!((D|0)!=0?(D|0)==(~f[i>>2]|0):0)){f[p>>2]=866;f[p+4>>2]=651;f[p+8>>2]=1579;vc(E,812,p)|0;Ub(E)|0}if(!(i&7)){Nb(i,0,0,1,0)|0;break}else{f[q>>2]=866;f[q+4>>2]=2506;f[q+8>>2]=1232;vc(E,812,q)|0;Ub(E)|0;break}}while(0);i=f[k>>2]|0;i=i|0?i:1;k=Db((i<<1)+8|0,0)|0;if(!k){f[l>>2]=0;g=0;break}else{f[k+4>>2]=i;f[k>>2]=~i;f[l>>2]=k+8;s=24;break}}else s=24;while(0);a:do if((s|0)==24){D=a+24|0;b[D>>0]=n;b[a+25>>0]=m;l=a+176|0;k=0;do{B=b[e+k>>0]|0;i=B&255;if(B<<24>>24){if(!(f[K+(i<<2)>>2]|0)){f[w>>2]=866;f[w+4>>2]=2276;f[w+8>>2]=977;vc(E,812,w)|0;Ub(E)|0}B=t+(i<<2)|0;i=f[B>>2]|0;f[B>>2]=i+1;if(i>>>0>=r>>>0){f[v>>2]=866;f[v+4>>2]=2280;f[v+8>>2]=990;vc(E,812,v)|0;Ub(E)|0}d[(f[l>>2]|0)+(i<<1)>>1]=k}k=k+1|0}while((k|0)!=(c|0));A=(h[D>>0]|0)>>>0 >>0?g:0;B=a+8|0;f[B>>2]=A;z=(A|0)!=0;if(z){y=1<>>0>(f[i>>2]|0)>>>0){f[i>>2]=y;l=a+168|0;i=f[l>>2]|0;do if(i|0){w=f[i+-4>>2]|0;i=i+-8|0;if(!((w|0)!=0?(w|0)==(~f[i>>2]|0):0)){f[x>>2]=866;f[x+4>>2]=651;f[x+8>>2]=1579;vc(E,812,x)|0;Ub(E)|0}if(!(i&7)){Nb(i,0,0,1,0)|0;break}else{f[C>>2]=866;f[C+4>>2]=2506;f[C+8>>2]=1232;vc(E,812,C)|0;Ub(E)|0;break}}while(0);i=y<<2;k=Db(i+8|0,0)|0;if(!k){f[l>>2]=0;g=0;break a}else{C=k+8|0;f[k+4>>2]=y;f[k>>2]=~y;f[l>>2]=C;k=C;break}}else{k=a+168|0;i=y<<2;l=k;k=f[k>>2]|0}while(0);Ib(k|0,-1,i|0)|0;v=a+176|0;t=1;do{if(f[K+(t<<2)>>2]|0){w=A-t|0;x=1< >2]|0;if(i>>>0>=16){f[G>>2]=866;f[G+4>>2]=1960;f[G+8>>2]=1453;vc(E,812,G)|0;Ub(E)|0}c=f[a+28+(i<<2)>>2]|0;c=(c|0)==0?-1:(c+-1|0)>>>(16-t|0);if(k>>>0<=c>>>0){r=(f[a+96+(i<<2)>>2]|0)-k|0;s=t<<16;do{i=j[(f[v>>2]|0)+(r+k<<1)>>1]|0;if((h[e+i>>0]|0|0)!=(t|0)){f[H>>2]=866;f[H+4>>2]=2322;f[H+8>>2]=1019;vc(E,812,H)|0;Ub(E)|0}q=k< >>0>=y>>>0){f[I>>2]=866;f[I+4>>2]=2328;f[I+8>>2]=1053;vc(E,812,I)|0;Ub(E)|0}i=f[l>>2]|0;if((f[i+(p<<2)>>2]|0)!=-1){f[J>>2]=866;f[J+4>>2]=2330;f[J+8>>2]=1076;vc(E,812,J)|0;Ub(E)|0;i=f[l>>2]|0}f[i+(p<<2)>>2]=o;n=n+1|0}while(n>>>0 >>0);k=k+1|0}while(k>>>0<=c>>>0)}}t=t+1|0}while(A>>>0>=t>>>0)}i=a+96|0;f[i>>2]=(f[i>>2]|0)-(f[F>>2]|0);i=a+100|0;f[i>>2]=(f[i>>2]|0)-(f[F+4>>2]|0);i=a+104|0;f[i>>2]=(f[i>>2]|0)-(f[F+8>>2]|0);i=a+108|0;f[i>>2]=(f[i>>2]|0)-(f[F+12>>2]|0);i=a+112|0;f[i>>2]=(f[i>>2]|0)-(f[F+16>>2]|0);i=a+116|0;f[i>>2]=(f[i>>2]|0)-(f[F+20>>2]|0);i=a+120|0;f[i>>2]=(f[i>>2]|0)-(f[F+24>>2]|0);i=a+124|0;f[i>>2]=(f[i>>2]|0)-(f[F+28>>2]|0);i=a+128|0;f[i>>2]=(f[i>>2]|0)-(f[F+32>>2]|0);i=a+132|0;f[i>>2]=(f[i>>2]|0)-(f[F+36>>2]|0);i=a+136|0;f[i>>2]=(f[i>>2]|0)-(f[F+40>>2]|0);i=a+140|0;f[i>>2]=(f[i>>2]|0)-(f[F+44>>2]|0);i=a+144|0;f[i>>2]=(f[i>>2]|0)-(f[F+48>>2]|0);i=a+148|0;f[i>>2]=(f[i>>2]|0)-(f[F+52>>2]|0);i=a+152|0;f[i>>2]=(f[i>>2]|0)-(f[F+56>>2]|0);i=a+156|0;f[i>>2]=(f[i>>2]|0)-(f[F+60>>2]|0);i=a+16|0;f[i>>2]=0;k=a+20|0;f[k>>2]=h[D>>0];b:do if(z){do{if(!g)break b;J=g;g=g+-1|0}while(!(f[K+(J<<2)>>2]|0));f[i>>2]=f[a+28+(g<<2)>>2];g=A+1|0;f[k>>2]=g;if(g>>>0<=m>>>0){while(1){if(f[K+(g<<2)>>2]|0)break;g=g+1|0;if(g>>>0>m>>>0)break b}f[k>>2]=g}}while(0);f[a+92>>2]=-1;f[a+160>>2]=1048575;f[a+12>>2]=32-(f[B>>2]|0);g=1}while(0);K=g;u=L;return K|0}function Ra(a,c,d,e,g,i,j,k){a=a|0;c=c|0;d=d|0;e=e|0;g=g|0;i=i|0;j=j|0;k=k|0;var l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0;ga=u;u=u+656|0;ea=ga+112|0;ca=ga+96|0;ba=ga+80|0;aa=ga+64|0;$=ga+48|0;fa=ga+32|0;da=ga+16|0;_=ga;Y=ga+144|0;Z=ga+128|0;N=a+240|0;O=f[N>>2]|0;P=a+256|0;Q=f[P>>2]|0;W=b[(f[a+88>>2]|0)+17>>0]|0;R=W&255;S=e>>>2;if(!(W<<24>>24)){u=ga;return 1}T=(k|0)==0;U=j+-1|0;V=U<<4;W=k+-1|0;H=(i&1|0)!=0;I=e<<1;J=a+92|0;K=a+116|0;L=a+140|0;M=a+236|0;G=(g&1|0)!=0;F=a+188|0;B=a+252|0;C=S+1|0;D=S+2|0;E=S+3|0;A=0;i=0;d=0;g=1;do{if(!T){y=f[c+(A<<2)>>2]|0;z=0;while(1){w=z&1;m=(w|0)==0;v=(w<<5^32)+-16|0;w=(w<<1^2)+-1|0;t=m?j:-1;l=m?0:U;a=(z|0)==(W|0);x=H&a;if((l|0)!=(t|0)){s=H&a^1;r=m?y:y+V|0;while(1){if((g|0)==1)g=bb(J,K)|0|512;q=g&7;g=g>>>3;m=h[1539+q>>0]|0;a=0;do{n=(bb(J,L)|0)+d|0;o=n-O|0;p=o>>31;d=p&n|o&~p;if((f[N>>2]|0)>>>0<=d>>>0){f[_>>2]=866;f[_+4>>2]=910;f[_+8>>2]=1497;vc(Y,812,_)|0;Ub(Y)|0}f[Z+(a<<2)>>2]=f[(f[M>>2]|0)+(d<<2)>>2];a=a+1|0}while(a>>>0 >>0);p=G&(l|0)==(U|0);if(x|p){o=0;do{a=r+(X(o,e)|0)|0;n=(o|0)==0|s;m=o<<1;ia=(bb(J,F)|0)+i|0;ha=ia-Q|0;i=ha>>31;i=i&ia|ha&~i;do if(!p){if(n){f[a>>2]=f[Z+((h[1547+(q<<2)+m>>0]|0)<<2)>>2];if((f[P>>2]|0)>>>0<=i>>>0){f[ba>>2]=866;f[ba+4>>2]=910;f[ba+8>>2]=1497;vc(Y,812,ba)|0;Ub(Y)|0}f[a+4>>2]=f[(f[B>>2]|0)+(i<<2)>>2]}a=a+8|0;ha=(bb(J,F)|0)+i|0;ia=ha-Q|0;i=ia>>31;i=i&ha|ia&~i;if(n){f[a>>2]=f[Z+((h[(m|1)+(1547+(q<<2))>>0]|0)<<2)>>2];if((f[P>>2]|0)>>>0<=i>>>0){f[ea>>2]=866;f[ea+4>>2]=910;f[ea+8>>2]=1497;vc(Y,812,ea)|0;Ub(Y)|0}f[a+4>>2]=f[(f[B>>2]|0)+(i<<2)>>2]}}else{if(!n){ha=(bb(J,F)|0)+i|0;ia=ha-Q|0;i=ia>>31;i=i&ha|ia&~i;break}f[a>>2]=f[Z+((h[1547+(q<<2)+m>>0]|0)<<2)>>2];if((f[P>>2]|0)>>>0<=i>>>0){f[ca>>2]=866;f[ca+4>>2]=910;f[ca+8>>2]=1497;vc(Y,812,ca)|0;Ub(Y)|0}f[a+4>>2]=f[(f[B>>2]|0)+(i<<2)>>2];ha=(bb(J,F)|0)+i|0;ia=ha-Q|0;i=ia>>31;i=i&ha|ia&~i}while(0);o=o+1|0}while((o|0)!=2)}else{f[r>>2]=f[Z+((h[1547+(q<<2)>>0]|0)<<2)>>2];ha=(bb(J,F)|0)+i|0;ia=ha-Q|0;i=ia>>31;i=i&ha|ia&~i;if((f[P>>2]|0)>>>0<=i>>>0){f[da>>2]=866;f[da+4>>2]=910;f[da+8>>2]=1497;vc(Y,812,da)|0;Ub(Y)|0}f[r+4>>2]=f[(f[B>>2]|0)+(i<<2)>>2];f[r+8>>2]=f[Z+((h[1547+(q<<2)+1>>0]|0)<<2)>>2];ha=(bb(J,F)|0)+i|0;ia=ha-Q|0;i=ia>>31;i=i&ha|ia&~i;if((f[P>>2]|0)>>>0<=i>>>0){f[fa>>2]=866;f[fa+4>>2]=910;f[fa+8>>2]=1497;vc(Y,812,fa)|0;Ub(Y)|0}f[r+12>>2]=f[(f[B>>2]|0)+(i<<2)>>2];f[r+(S<<2)>>2]=f[Z+((h[1547+(q<<2)+2>>0]|0)<<2)>>2];ha=(bb(J,F)|0)+i|0;ia=ha-Q|0;i=ia>>31;i=i&ha|ia&~i;if((f[P>>2]|0)>>>0<=i>>>0){f[$>>2]=866;f[$+4>>2]=910;f[$+8>>2]=1497;vc(Y,812,$)|0;Ub(Y)|0}f[r+(C<<2)>>2]=f[(f[B>>2]|0)+(i<<2)>>2];f[r+(D<<2)>>2]=f[Z+((h[1547+(q<<2)+3>>0]|0)<<2)>>2];ha=(bb(J,F)|0)+i|0;ia=ha-Q|0;i=ia>>31;i=i&ha|ia&~i;if((f[P>>2]|0)>>>0<=i>>>0){f[aa>>2]=866;f[aa+4>>2]=910;f[aa+8>>2]=1497;vc(Y,812,aa)|0;Ub(Y)|0}f[r+(E<<2)>>2]=f[(f[B>>2]|0)+(i<<2)>>2]}l=w+l|0;if((l|0)==(t|0))break;else r=r+v|0}}z=z+1|0;if((z|0)==(k|0))break;else y=y+I|0}}A=A+1|0}while((A|0)!=(R|0));u=ga;return 1}function Sa(a,c,d,e,g,i,k,l){a=a|0;c=c|0;d=d|0;e=e|0;g=g|0;i=i|0;k=k|0;l=l|0;var m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0;ka=u;u=u+640|0;ha=ka+80|0;ga=ka+64|0;fa=ka+48|0;ja=ka+32|0;ia=ka+16|0;ea=ka;ca=ka+128|0;da=ka+112|0;P=ka+96|0;Q=a+272|0;R=f[Q>>2]|0;ba=f[a+88>>2]|0;S=(h[ba+63>>0]|0)<<8|(h[ba+64>>0]|0);ba=b[ba+17>>0]|0;T=ba&255;if(!(ba<<24>>24)){u=ka;return 1}U=(l|0)==0;V=k+-1|0;W=V<<5;X=l+-1|0;Y=e<<1;Z=a+92|0;_=a+116|0;$=a+164|0;aa=a+268|0;ba=a+212|0;O=(g&1|0)==0;N=(i&1|0)==0;M=a+288|0;L=a+284|0;K=0;a=0;i=0;g=0;d=0;m=1;do{if(!U){I=f[c+(K<<2)>>2]|0;J=0;while(1){H=J&1;o=(H|0)==0;G=(H<<6^64)+-32|0;H=(H<<1^2)+-1|0;E=o?k:-1;n=o?0:V;if((n|0)!=(E|0)){F=N|(J|0)!=(X|0);D=o?I:I+W|0;while(1){if((m|0)==1)m=bb(Z,_)|0|512;C=m&7;m=m>>>3;p=h[1539+C>>0]|0;o=0;do{z=(bb(Z,$)|0)+d|0;A=z-R|0;B=A>>31;d=B&z|A&~B;if((f[Q>>2]|0)>>>0<=d>>>0){f[ea>>2]=866;f[ea+4>>2]=910;f[ea+8>>2]=1497;vc(ca,812,ea)|0;Ub(ca)|0}f[da+(o<<2)>>2]=j[(f[aa>>2]|0)+(d<<1)>>1];o=o+1|0}while(o>>>0 >>0);o=0;do{z=(bb(Z,$)|0)+i|0;A=z-R|0;B=A>>31;i=B&z|A&~B;if((f[Q>>2]|0)>>>0<=i>>>0){f[ia>>2]=866;f[ia+4>>2]=910;f[ia+8>>2]=1497;vc(ca,812,ia)|0;Ub(ca)|0}f[P+(o<<2)>>2]=j[(f[aa>>2]|0)+(i<<1)>>1];o=o+1|0}while(o>>>0
>>0);B=O|(n|0)!=(V|0);z=0;A=D;while(1){w=F|(z|0)==0;x=z<<1;if(B){t=0;v=A;while(1){y=(bb(Z,ba)|0)+g|0;s=y-S|0;g=s>>31;g=g&y|s&~g;s=(bb(Z,ba)|0)+a|0;y=s-S|0;a=y>>31;a=a&s|y&~a;if(w){s=h[t+x+(1547+(C<<2))>>0]|0;p=g*3|0;o=f[M>>2]|0;if(o>>>0<=p>>>0){f[ja>>2]=866;f[ja+4>>2]=910;f[ja+8>>2]=1497;vc(ca,812,ja)|0;Ub(ca)|0;o=f[M>>2]|0}q=f[L>>2]|0;p=q+(p<<1)|0;r=a*3|0;if(o>>>0>r>>>0)o=q;else{f[fa>>2]=866;f[fa+4>>2]=910;f[fa+8>>2]=1497;vc(ca,812,fa)|0;Ub(ca)|0;o=f[L>>2]|0}y=o+(r<<1)|0;f[v>>2]=(j[p>>1]|0)<<16|f[da+(s<<2)>>2];f[v+4>>2]=(j[p+4>>1]|0)<<16|(j[p+2>>1]|0);f[v+8>>2]=(j[y>>1]|0)<<16|f[P+(s<<2)>>2];f[v+12>>2]=(j[y+4>>1]|0)<<16|(j[y+2>>1]|0)}t=t+1|0;if((t|0)==2)break;else v=v+16|0}}else{y=w^1;w=1547+(C<<2)+x|0;t=0;v=A;while(1){x=(bb(Z,ba)|0)+g|0;s=x-S|0;g=s>>31;g=g&x|s&~g;s=(bb(Z,ba)|0)+a|0;x=s-S|0;a=x>>31;a=a&s|x&~a;if(!((t|0)!=0|y)){s=h[w>>0]|0;p=g*3|0;o=f[M>>2]|0;if(o>>>0<=p>>>0){f[ga>>2]=866;f[ga+4>>2]=910;f[ga+8>>2]=1497;vc(ca,812,ga)|0;Ub(ca)|0;o=f[M>>2]|0}q=f[L>>2]|0;p=q+(p<<1)|0;r=a*3|0;if(o>>>0>r>>>0)o=q;else{f[ha>>2]=866;f[ha+4>>2]=910;f[ha+8>>2]=1497;vc(ca,812,ha)|0;Ub(ca)|0;o=f[L>>2]|0}x=o+(r<<1)|0;f[v>>2]=(j[p>>1]|0)<<16|f[da+(s<<2)>>2];f[v+4>>2]=(j[p+4>>1]|0)<<16|(j[p+2>>1]|0);f[v+8>>2]=(j[x>>1]|0)<<16|f[P+(s<<2)>>2];f[v+12>>2]=(j[x+4>>1]|0)<<16|(j[x+2>>1]|0)}t=t+1|0;if((t|0)==2)break;else v=v+16|0}}z=z+1|0;if((z|0)==2)break;else A=A+e|0}n=H+n|0;if((n|0)==(E|0))break;else D=D+G|0}}J=J+1|0;if((J|0)==(l|0))break;else I=I+Y|0}}K=K+1|0}while((K|0)!=(T|0));u=ka;return 1}function Ta(a){a=a|0;var b=0,c=0,d=0,e=0,g=0,h=0,i=0,j=0;if(!a)return;c=a+-8|0;e=f[1148]|0;a=f[a+-4>>2]|0;b=a&-8;j=c+b|0;do if(!(a&1)){d=f[c>>2]|0;if(!(a&3))return;h=c+(0-d)|0;g=d+b|0;if(h>>>0
>>0)return;if((h|0)==(f[1149]|0)){a=j+4|0;b=f[a>>2]|0;if((b&3|0)!=3){i=h;b=g;break}f[1146]=g;f[a>>2]=b&-2;f[h+4>>2]=g|1;f[h+g>>2]=g;return}c=d>>>3;if(d>>>0<256){a=f[h+8>>2]|0;b=f[h+12>>2]|0;if((b|0)==(a|0)){f[1144]=f[1144]&~(1< >2]=b;f[b+8>>2]=a;i=h;b=g;break}}e=f[h+24>>2]|0;a=f[h+12>>2]|0;do if((a|0)==(h|0)){c=h+16|0;b=c+4|0;a=f[b>>2]|0;if(!a){a=f[c>>2]|0;if(!a){a=0;break}else b=c}while(1){c=a+20|0;d=f[c>>2]|0;if(d|0){a=d;b=c;continue}c=a+16|0;d=f[c>>2]|0;if(!d)break;else{a=d;b=c}}f[b>>2]=0}else{i=f[h+8>>2]|0;f[i+12>>2]=a;f[a+8>>2]=i}while(0);if(e){b=f[h+28>>2]|0;c=4880+(b<<2)|0;if((h|0)==(f[c>>2]|0)){f[c>>2]=a;if(!a){f[1145]=f[1145]&~(1<>2]|0)!=(h|0)&1)<<2)>>2]=a;if(!a){i=h;b=g;break}}f[a+24>>2]=e;b=h+16|0;c=f[b>>2]|0;if(c|0){f[a+16>>2]=c;f[c+24>>2]=a}b=f[b+4>>2]|0;if(b){f[a+20>>2]=b;f[b+24>>2]=a;i=h;b=g}else{i=h;b=g}}else{i=h;b=g}}else{i=c;h=c}while(0);if(h>>>0>=j>>>0)return;a=j+4|0;d=f[a>>2]|0;if(!(d&1))return;if(!(d&2)){a=f[1149]|0;if((j|0)==(f[1150]|0)){j=(f[1147]|0)+b|0;f[1147]=j;f[1150]=i;f[i+4>>2]=j|1;if((i|0)!=(a|0))return;f[1149]=0;f[1146]=0;return}if((j|0)==(a|0)){j=(f[1146]|0)+b|0;f[1146]=j;f[1149]=h;f[i+4>>2]=j|1;f[h+j>>2]=j;return}e=(d&-8)+b|0;c=d>>>3;do if(d>>>0<256){b=f[j+8>>2]|0;a=f[j+12>>2]|0;if((a|0)==(b|0)){f[1144]=f[1144]&~(1< >2]=a;f[a+8>>2]=b;break}}else{g=f[j+24>>2]|0;a=f[j+12>>2]|0;do if((a|0)==(j|0)){c=j+16|0;b=c+4|0;a=f[b>>2]|0;if(!a){a=f[c>>2]|0;if(!a){c=0;break}else b=c}while(1){c=a+20|0;d=f[c>>2]|0;if(d|0){a=d;b=c;continue}c=a+16|0;d=f[c>>2]|0;if(!d)break;else{a=d;b=c}}f[b>>2]=0;c=a}else{c=f[j+8>>2]|0;f[c+12>>2]=a;f[a+8>>2]=c;c=a}while(0);if(g|0){a=f[j+28>>2]|0;b=4880+(a<<2)|0;if((j|0)==(f[b>>2]|0)){f[b>>2]=c;if(!c){f[1145]=f[1145]&~(1<>2]|0)!=(j|0)&1)<<2)>>2]=c;if(!c)break}f[c+24>>2]=g;a=j+16|0;b=f[a>>2]|0;if(b|0){f[c+16>>2]=b;f[b+24>>2]=c}a=f[a+4>>2]|0;if(a|0){f[c+20>>2]=a;f[a+24>>2]=c}}}while(0);f[i+4>>2]=e|1;f[h+e>>2]=e;if((i|0)==(f[1149]|0)){f[1146]=e;return}}else{f[a>>2]=d&-2;f[i+4>>2]=b|1;f[h+b>>2]=b;e=b}a=e>>>3;if(e>>>0<256){c=4616+(a<<1<<2)|0;b=f[1144]|0;a=1<>2]|0}f[b>>2]=i;f[a+12>>2]=i;f[i+8>>2]=a;f[i+12>>2]=c;return}a=e>>>8;if(a)if(e>>>0>16777215)a=31;else{h=(a+1048320|0)>>>16&8;j=a< >>16&4;j=j< >>16&2;a=14-(g|h|a)+(j<>>15)|0;a=e>>>(a+7|0)&1|a<<1}else a=0;d=4880+(a<<2)|0;f[i+28>>2]=a;f[i+20>>2]=0;f[i+16>>2]=0;b=f[1145]|0;c=1<>>1)|0);c=f[d>>2]|0;while(1){if((f[c+4>>2]&-8|0)==(e|0)){a=73;break}d=c+16+(b>>>31<<2)|0;a=f[d>>2]|0;if(!a){a=72;break}else{b=b<<1;c=a}}if((a|0)==72){f[d>>2]=i;f[i+24>>2]=c;f[i+12>>2]=i;f[i+8>>2]=i;break}else if((a|0)==73){h=c+8|0;j=f[h>>2]|0;f[j+12>>2]=i;f[h>>2]=i;f[i+8>>2]=j;f[i+12>>2]=c;f[i+24>>2]=0;break}}else{f[1145]=b|c;f[d>>2]=i;f[i+24>>2]=d;f[i+12>>2]=i;f[i+8>>2]=i}while(0);j=(f[1152]|0)+-1|0;f[1152]=j;if(!j)a=5032;else return;while(1){a=f[a>>2]|0;if(!a)break;else a=a+8|0}f[1152]=-1;return}function Ua(a,c,d,e,g,i,k,l){a=a|0;c=c|0;d=d|0;e=e|0;g=g|0;i=i|0;k=k|0;l=l|0;var m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=0,la=0,ma=0,na=0,oa=0,pa=0;pa=u;u=u+640|0;ma=pa+80|0;la=pa+64|0;ka=pa+48|0;oa=pa+32|0;na=pa+16|0;ja=pa;ha=pa+128|0;ia=pa+112|0;N=pa+96|0;O=a+240|0;P=f[O>>2]|0;Q=a+256|0;R=f[Q>>2]|0;S=a+272|0;T=f[S>>2]|0;ga=f[a+88>>2]|0;U=(h[ga+63>>0]|0)<<8|(h[ga+64>>0]|0);ga=b[ga+17>>0]|0;V=ga&255;if(!(ga<<24>>24)){u=pa;return 1}W=(l|0)==0;X=k+-1|0;Y=X<<5;Z=l+-1|0;_=e<<1;$=a+92|0;aa=a+116|0;ba=a+164|0;ca=a+268|0;da=a+140|0;ea=a+236|0;fa=a+212|0;ga=a+188|0;M=(g&1|0)==0;L=(i&1|0)==0;J=a+288|0;K=a+284|0;I=a+252|0;H=0;a=0;i=0;g=0;d=0;m=1;do{if(!W){F=f[c+(H<<2)>>2]|0;G=0;while(1){E=G&1;o=(E|0)==0;D=(E<<6^64)+-32|0;E=(E<<1^2)+-1|0;B=o?k:-1;n=o?0:X;if((n|0)!=(B|0)){C=L|(G|0)!=(Z|0);A=o?F:F+Y|0;while(1){if((m|0)==1)m=bb($,aa)|0|512;z=m&7;m=m>>>3;p=h[1539+z>>0]|0;o=0;do{w=(bb($,ba)|0)+i|0;x=w-T|0;y=x>>31;i=y&w|x&~y;if((f[S>>2]|0)>>>0<=i>>>0){f[ja>>2]=866;f[ja+4>>2]=910;f[ja+8>>2]=1497;vc(ha,812,ja)|0;Ub(ha)|0}f[N+(o<<2)>>2]=j[(f[ca>>2]|0)+(i<<1)>>1];o=o+1|0}while(o>>>0 >>0);o=0;do{w=(bb($,da)|0)+d|0;x=w-P|0;y=x>>31;d=y&w|x&~y;if((f[O>>2]|0)>>>0<=d>>>0){f[na>>2]=866;f[na+4>>2]=910;f[na+8>>2]=1497;vc(ha,812,na)|0;Ub(ha)|0}f[ia+(o<<2)>>2]=f[(f[ea>>2]|0)+(d<<2)>>2];o=o+1|0}while(o>>>0
>>0);y=M|(n|0)!=(X|0);w=0;x=A;while(1){s=C|(w|0)==0;t=w<<1;if(y){q=0;r=x;while(1){v=(bb($,fa)|0)+a|0;p=v-U|0;a=p>>31;a=a&v|p&~a;p=(bb($,ga)|0)+g|0;v=p-R|0;g=v>>31;g=g&p|v&~g;if(s){o=h[q+t+(1547+(z<<2))>>0]|0;p=a*3|0;if((f[J>>2]|0)>>>0<=p>>>0){f[oa>>2]=866;f[oa+4>>2]=910;f[oa+8>>2]=1497;vc(ha,812,oa)|0;Ub(ha)|0}v=(f[K>>2]|0)+(p<<1)|0;f[r>>2]=(j[v>>1]|0)<<16|f[N+(o<<2)>>2];f[r+4>>2]=(j[v+4>>1]|0)<<16|(j[v+2>>1]|0);f[r+8>>2]=f[ia+(o<<2)>>2];if((f[Q>>2]|0)>>>0<=g>>>0){f[ka>>2]=866;f[ka+4>>2]=910;f[ka+8>>2]=1497;vc(ha,812,ka)|0;Ub(ha)|0}f[r+12>>2]=f[(f[I>>2]|0)+(g<<2)>>2]}q=q+1|0;if((q|0)==2)break;else r=r+16|0}}else{v=s^1;s=1547+(z<<2)+t|0;q=0;r=x;while(1){t=(bb($,fa)|0)+a|0;p=t-U|0;a=p>>31;a=a&t|p&~a;p=(bb($,ga)|0)+g|0;t=p-R|0;g=t>>31;g=g&p|t&~g;if(!((q|0)!=0|v)){o=h[s>>0]|0;p=a*3|0;if((f[J>>2]|0)>>>0<=p>>>0){f[la>>2]=866;f[la+4>>2]=910;f[la+8>>2]=1497;vc(ha,812,la)|0;Ub(ha)|0}t=(f[K>>2]|0)+(p<<1)|0;f[r>>2]=(j[t>>1]|0)<<16|f[N+(o<<2)>>2];f[r+4>>2]=(j[t+4>>1]|0)<<16|(j[t+2>>1]|0);f[r+8>>2]=f[ia+(o<<2)>>2];if((f[Q>>2]|0)>>>0<=g>>>0){f[ma>>2]=866;f[ma+4>>2]=910;f[ma+8>>2]=1497;vc(ha,812,ma)|0;Ub(ha)|0}f[r+12>>2]=f[(f[I>>2]|0)+(g<<2)>>2]}q=q+1|0;if((q|0)==2)break;else r=r+16|0}}w=w+1|0;if((w|0)==2)break;else x=x+e|0}n=E+n|0;if((n|0)==(B|0))break;else A=A+D|0}}G=G+1|0;if((G|0)==(l|0))break;else F=F+_|0}}H=H+1|0}while((H|0)!=(V|0));u=pa;return 1}function Va(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,g=0,h=0,i=0,j=0;j=a+b|0;c=f[a+4>>2]|0;do if(!(c&1)){d=f[a>>2]|0;if(!(c&3))return;g=a+(0-d)|0;h=d+b|0;if((g|0)==(f[1149]|0)){a=j+4|0;c=f[a>>2]|0;if((c&3|0)!=3){i=g;c=h;break}f[1146]=h;f[a>>2]=c&-2;f[g+4>>2]=h|1;f[g+h>>2]=h;return}b=d>>>3;if(d>>>0<256){a=f[g+8>>2]|0;c=f[g+12>>2]|0;if((c|0)==(a|0)){f[1144]=f[1144]&~(1<>2]=c;f[c+8>>2]=a;i=g;c=h;break}}e=f[g+24>>2]|0;a=f[g+12>>2]|0;do if((a|0)==(g|0)){b=g+16|0;c=b+4|0;a=f[c>>2]|0;if(!a){a=f[b>>2]|0;if(!a){a=0;break}else c=b}while(1){b=a+20|0;d=f[b>>2]|0;if(d|0){a=d;c=b;continue}b=a+16|0;d=f[b>>2]|0;if(!d)break;else{a=d;c=b}}f[c>>2]=0}else{i=f[g+8>>2]|0;f[i+12>>2]=a;f[a+8>>2]=i}while(0);if(e){c=f[g+28>>2]|0;b=4880+(c<<2)|0;if((g|0)==(f[b>>2]|0)){f[b>>2]=a;if(!a){f[1145]=f[1145]&~(1<
>2]|0)!=(g|0)&1)<<2)>>2]=a;if(!a){i=g;c=h;break}}f[a+24>>2]=e;c=g+16|0;b=f[c>>2]|0;if(b|0){f[a+16>>2]=b;f[b+24>>2]=a}c=f[c+4>>2]|0;if(c){f[a+20>>2]=c;f[c+24>>2]=a;i=g;c=h}else{i=g;c=h}}else{i=g;c=h}}else{i=a;c=b}while(0);a=j+4|0;d=f[a>>2]|0;if(!(d&2)){a=f[1149]|0;if((j|0)==(f[1150]|0)){j=(f[1147]|0)+c|0;f[1147]=j;f[1150]=i;f[i+4>>2]=j|1;if((i|0)!=(a|0))return;f[1149]=0;f[1146]=0;return}if((j|0)==(a|0)){j=(f[1146]|0)+c|0;f[1146]=j;f[1149]=i;f[i+4>>2]=j|1;f[i+j>>2]=j;return}g=(d&-8)+c|0;b=d>>>3;do if(d>>>0<256){c=f[j+8>>2]|0;a=f[j+12>>2]|0;if((a|0)==(c|0)){f[1144]=f[1144]&~(1<>2]=a;f[a+8>>2]=c;break}}else{e=f[j+24>>2]|0;a=f[j+12>>2]|0;do if((a|0)==(j|0)){b=j+16|0;c=b+4|0;a=f[c>>2]|0;if(!a){a=f[b>>2]|0;if(!a){b=0;break}else c=b}while(1){b=a+20|0;d=f[b>>2]|0;if(d|0){a=d;c=b;continue}b=a+16|0;d=f[b>>2]|0;if(!d)break;else{a=d;c=b}}f[c>>2]=0;b=a}else{b=f[j+8>>2]|0;f[b+12>>2]=a;f[a+8>>2]=b;b=a}while(0);if(e|0){a=f[j+28>>2]|0;c=4880+(a<<2)|0;if((j|0)==(f[c>>2]|0)){f[c>>2]=b;if(!b){f[1145]=f[1145]&~(1<>2]|0)!=(j|0)&1)<<2)>>2]=b;if(!b)break}f[b+24>>2]=e;a=j+16|0;c=f[a>>2]|0;if(c|0){f[b+16>>2]=c;f[c+24>>2]=b}a=f[a+4>>2]|0;if(a|0){f[b+20>>2]=a;f[a+24>>2]=b}}}while(0);f[i+4>>2]=g|1;f[i+g>>2]=g;if((i|0)==(f[1149]|0)){f[1146]=g;return}else c=g}else{f[a>>2]=d&-2;f[i+4>>2]=c|1;f[i+c>>2]=c}a=c>>>3;if(c>>>0<256){b=4616+(a<<1<<2)|0;c=f[1144]|0;a=1<>2]|0}f[c>>2]=i;f[a+12>>2]=i;f[i+8>>2]=a;f[i+12>>2]=b;return}a=c>>>8;if(a)if(c>>>0>16777215)a=31;else{h=(a+1048320|0)>>>16&8;j=a< >>16&4;j=j< >>16&2;a=14-(g|h|a)+(j<>>15)|0;a=c>>>(a+7|0)&1|a<<1}else a=0;e=4880+(a<<2)|0;f[i+28>>2]=a;f[i+20>>2]=0;f[i+16>>2]=0;b=f[1145]|0;d=1<>2]=i;f[i+24>>2]=e;f[i+12>>2]=i;f[i+8>>2]=i;return}b=c<<((a|0)==31?0:25-(a>>>1)|0);d=f[e>>2]|0;while(1){if((f[d+4>>2]&-8|0)==(c|0)){a=69;break}e=d+16+(b>>>31<<2)|0;a=f[e>>2]|0;if(!a){a=68;break}else{b=b<<1;d=a}}if((a|0)==68){f[e>>2]=i;f[i+24>>2]=d;f[i+12>>2]=i;f[i+8>>2]=i;return}else if((a|0)==69){h=d+8|0;j=f[h>>2]|0;f[j+12>>2]=i;f[h>>2]=i;f[i+8>>2]=j;f[i+12>>2]=d;f[i+24>>2]=0;return}}function Wa(a){a=a|0;var c=0,e=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0;S=u;u=u+2416|0;k=S;j=S+1904|0;R=S+1880|0;O=S+980|0;P=S+80|0;Q=S+16|0;e=f[a+88>>2]|0;M=(h[e+63>>0]|0)<<8|(h[e+64>>0]|0);N=a+92|0;c=(f[a+4>>2]|0)+((h[e+58>>0]|0)<<8|(h[e+57>>0]|0)<<16|(h[e+59>>0]|0))|0;e=(h[e+61>>0]|0)<<8|(h[e+60>>0]|0)<<16|(h[e+62>>0]|0);if(!e){R=0;u=S;return R|0}f[N>>2]=c;f[a+96>>2]=c;f[a+104>>2]=e;f[a+100>>2]=c+e;f[a+108>>2]=0;f[a+112>>2]=0;f[R+20>>2]=0;f[R>>2]=0;f[R+4>>2]=0;f[R+8>>2]=0;f[R+12>>2]=0;b[R+16>>0]=0;if(Pa(N,R)|0){c=0;e=-7;g=-7;while(1){f[O+(c<<2)>>2]=g;f[P+(c<<2)>>2]=e;i=(g|0)>6;c=c+1|0;if((c|0)==225)break;else{e=(i&1)+e|0;g=i?-7:g+1|0}}c=Q;e=c+64|0;do{f[c>>2]=0;c=c+4|0}while((c|0)<(e|0));i=a+284|0;e=M*3|0;g=a+288|0;c=f[g>>2]|0;a:do if((c|0)==(e|0))l=13;else{if(c>>>0<=e>>>0){do if((f[a+292>>2]|0)>>>0 >>0)if(fb(i,e,(c+1|0)==(e|0),2,0)|0){c=f[g>>2]|0;break}else{b[a+296>>0]=1;c=0;break a}while(0);Ib((f[i>>2]|0)+(c<<1)|0,0,e-c<<1|0)|0}f[g>>2]=e;l=13}while(0);do if((l|0)==13){if(!M){f[k>>2]=866;f[k+4>>2]=910;f[k+8>>2]=1497;vc(j,812,k)|0;Ub(j)|0;c=1;break}x=Q+4|0;y=Q+8|0;z=Q+12|0;A=Q+16|0;B=Q+20|0;C=Q+24|0;D=Q+28|0;E=Q+32|0;F=Q+36|0;G=Q+40|0;H=Q+44|0;I=Q+48|0;J=Q+52|0;K=Q+56|0;L=Q+60|0;w=0;c=f[i>>2]|0;e=f[Q>>2]|0;g=f[x>>2]|0;i=f[y>>2]|0;a=f[z>>2]|0;j=f[A>>2]|0;k=f[B>>2]|0;l=f[C>>2]|0;m=f[D>>2]|0;n=f[E>>2]|0;o=f[F>>2]|0;p=f[G>>2]|0;q=f[H>>2]|0;r=0;s=0;t=0;v=0;while(1){U=bb(N,R)|0;e=e+(f[O+(U<<2)>>2]|0)&7;g=g+(f[P+(U<<2)>>2]|0)&7;U=bb(N,R)|0;i=i+(f[O+(U<<2)>>2]|0)&7;a=a+(f[P+(U<<2)>>2]|0)&7;U=bb(N,R)|0;j=j+(f[O+(U<<2)>>2]|0)&7;k=k+(f[P+(U<<2)>>2]|0)&7;U=bb(N,R)|0;l=l+(f[O+(U<<2)>>2]|0)&7;m=m+(f[P+(U<<2)>>2]|0)&7;U=bb(N,R)|0;n=n+(f[O+(U<<2)>>2]|0)&7;o=o+(f[P+(U<<2)>>2]|0)&7;U=bb(N,R)|0;p=p+(f[O+(U<<2)>>2]|0)&7;q=q+(f[P+(U<<2)>>2]|0)&7;U=bb(N,R)|0;r=r+(f[O+(U<<2)>>2]|0)&7;s=s+(f[P+(U<<2)>>2]|0)&7;U=bb(N,R)|0;t=t+(f[O+(U<<2)>>2]|0)&7;v=v+(f[P+(U<<2)>>2]|0)&7;U=h[1445+k>>0]|0;d[c>>1]=(h[1445+g>>0]|0)<<3|(h[1445+e>>0]|0)|(h[1445+i>>0]|0)<<6|(h[1445+a>>0]|0)<<9|(h[1445+j>>0]|0)<<12|U<<15;T=h[1445+p>>0]|0;d[c+2>>1]=(h[1445+l>>0]|0)<<2|U>>>1|(h[1445+m>>0]|0)<<5|(h[1445+n>>0]|0)<<8|(h[1445+o>>0]|0)<<11|T<<14;d[c+4>>1]=(h[1445+q>>0]|0)<<1|T>>>2|(h[1445+r>>0]|0)<<4|(h[1445+s>>0]|0)<<7|(h[1445+t>>0]|0)<<10|(h[1445+v>>0]|0)<<13;w=w+1|0;if(w>>>0>=M>>>0)break;else c=c+6|0}f[Q>>2]=e;f[x>>2]=g;f[y>>2]=i;f[z>>2]=a;f[A>>2]=j;f[B>>2]=k;f[C>>2]=l;f[D>>2]=m;f[E>>2]=n;f[F>>2]=o;f[G>>2]=p;f[H>>2]=q;f[I>>2]=r;f[J>>2]=s;f[K>>2]=t;f[L>>2]=v;c=1}while(0)}else c=0;Cb(R);U=c;u=S;return U|0}function Xa(a){a=a|0;var c=0,d=0,e=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0;D=u;u=u+1008|0;j=D;i=D+496|0;C=D+472|0;z=D+276|0;A=D+80|0;B=D+16|0;d=f[a+88>>2]|0;x=(h[d+47>>0]|0)<<8|(h[d+48>>0]|0);y=a+92|0;c=(f[a+4>>2]|0)+((h[d+42>>0]|0)<<8|(h[d+41>>0]|0)<<16|(h[d+43>>0]|0))|0;d=(h[d+45>>0]|0)<<8|(h[d+44>>0]|0)<<16|(h[d+46>>0]|0);if(!d){C=0;u=D;return C|0}f[y>>2]=c;f[a+96>>2]=c;f[a+104>>2]=d;f[a+100>>2]=c+d;f[a+108>>2]=0;f[a+112>>2]=0;f[C+20>>2]=0;f[C>>2]=0;f[C+4>>2]=0;f[C+8>>2]=0;f[C+12>>2]=0;b[C+16>>0]=0;if(Pa(y,C)|0){c=0;d=-3;e=-3;while(1){f[z+(c<<2)>>2]=e;f[A+(c<<2)>>2]=d;g=(e|0)>2;c=c+1|0;if((c|0)==49)break;else{d=(g&1)+d|0;e=g?-3:e+1|0}}c=B;d=c+64|0;do{f[c>>2]=0;c=c+4|0}while((c|0)<(d|0));e=a+252|0;d=a+256|0;c=f[d>>2]|0;a:do if((c|0)==(x|0))k=13;else{if(c>>>0<=x>>>0){do if((f[a+260>>2]|0)>>>0 >>0)if(fb(e,x,(c+1|0)==(x|0),4,0)|0){c=f[d>>2]|0;break}else{b[a+264>>0]=1;c=0;break a}while(0);Ib((f[e>>2]|0)+(c<<2)|0,0,x-c<<2|0)|0}f[d>>2]=x;k=13}while(0);do if((k|0)==13){if(!x){f[j>>2]=866;f[j+4>>2]=910;f[j+8>>2]=1497;vc(i,812,j)|0;Ub(i)|0;c=1;break}a=B+4|0;i=B+8|0;j=B+12|0;k=B+16|0;l=B+20|0;m=B+24|0;n=B+28|0;o=B+32|0;p=B+36|0;q=B+40|0;r=B+44|0;s=B+48|0;t=B+52|0;v=B+56|0;w=B+60|0;g=0;c=f[e>>2]|0;d=f[a>>2]|0;e=f[B>>2]|0;while(1){Q=bb(y,C)|0;e=e+(f[z+(Q<<2)>>2]|0)&3;d=d+(f[A+(Q<<2)>>2]|0)&3;Q=bb(y,C)|0;R=(f[i>>2]|0)+(f[z+(Q<<2)>>2]|0)&3;f[i>>2]=R;Q=(f[j>>2]|0)+(f[A+(Q<<2)>>2]|0)&3;f[j>>2]=Q;O=bb(y,C)|0;P=(f[k>>2]|0)+(f[z+(O<<2)>>2]|0)&3;f[k>>2]=P;O=(f[l>>2]|0)+(f[A+(O<<2)>>2]|0)&3;f[l>>2]=O;M=bb(y,C)|0;N=(f[m>>2]|0)+(f[z+(M<<2)>>2]|0)&3;f[m>>2]=N;M=(f[n>>2]|0)+(f[A+(M<<2)>>2]|0)&3;f[n>>2]=M;K=bb(y,C)|0;L=(f[o>>2]|0)+(f[z+(K<<2)>>2]|0)&3;f[o>>2]=L;K=(f[p>>2]|0)+(f[A+(K<<2)>>2]|0)&3;f[p>>2]=K;I=bb(y,C)|0;J=(f[q>>2]|0)+(f[z+(I<<2)>>2]|0)&3;f[q>>2]=J;I=(f[r>>2]|0)+(f[A+(I<<2)>>2]|0)&3;f[r>>2]=I;G=bb(y,C)|0;H=(f[s>>2]|0)+(f[z+(G<<2)>>2]|0)&3;f[s>>2]=H;G=(f[t>>2]|0)+(f[A+(G<<2)>>2]|0)&3;f[t>>2]=G;E=bb(y,C)|0;F=(f[v>>2]|0)+(f[z+(E<<2)>>2]|0)&3;f[v>>2]=F;E=(f[w>>2]|0)+(f[A+(E<<2)>>2]|0)&3;f[w>>2]=E;f[c>>2]=(h[1441+d>>0]|0)<<2|(h[1441+e>>0]|0)|(h[1441+R>>0]|0)<<4|(h[1441+Q>>0]|0)<<6|(h[1441+P>>0]|0)<<8|(h[1441+O>>0]|0)<<10|(h[1441+N>>0]|0)<<12|(h[1441+M>>0]|0)<<14|(h[1441+L>>0]|0)<<16|(h[1441+K>>0]|0)<<18|(h[1441+J>>0]|0)<<20|(h[1441+I>>0]|0)<<22|(h[1441+H>>0]|0)<<24|(h[1441+G>>0]|0)<<26|(h[1441+F>>0]|0)<<28|(h[1441+E>>0]|0)<<30;g=g+1|0;if(g>>>0>=x>>>0)break;else c=c+4|0}f[B>>2]=e;f[a>>2]=d;c=1}while(0)}else c=0;Cb(C);R=c;u=D;return R|0}function Ya(a,c,d,e,g,i,k,l){a=a|0;c=c|0;d=d|0;e=e|0;g=g|0;i=i|0;k=k|0;l=l|0;var m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,v=0,w=0,x=0,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0,_=0,$=0,aa=0;aa=u;u=u+592|0;Z=aa+48|0;$=aa+32|0;_=aa+16|0;Y=aa;W=aa+80|0;X=aa+64|0;I=a+272|0;J=f[I>>2]|0;V=f[a+88>>2]|0;K=(h[V+63>>0]|0)<<8|(h[V+64>>0]|0);V=b[V+17>>0]|0;L=V&255;if(!(V<<24>>24)){u=aa;return 1}M=(l|0)==0;N=k+-1|0;O=N<<4;P=l+-1|0;Q=e<<1;R=a+92|0;S=a+116|0;T=a+164|0;U=a+268|0;V=a+212|0;H=(g&1|0)==0;G=(i&1|0)==0;F=a+288|0;E=a+284|0;D=0;g=0;d=0;i=1;do{if(!M){B=f[c+(D<<2)>>2]|0;C=0;while(1){A=C&1;m=(A|0)==0;z=(A<<5^32)+-16|0;A=(A<<1^2)+-1|0;x=m?k:-1;a=m?0:N;if((a|0)!=(x|0)){y=G|(C|0)!=(P|0);w=m?B:B+O|0;while(1){if((i|0)==1)i=bb(R,S)|0|512;v=i&7;i=i>>>3;n=h[1539+v>>0]|0;m=0;do{r=(bb(R,T)|0)+d|0;s=r-J|0;t=s>>31;d=t&r|s&~t;if((f[I>>2]|0)>>>0<=d>>>0){f[Y>>2]=866;f[Y+4>>2]=910;f[Y+8>>2]=1497;vc(W,812,Y)|0;Ub(W)|0}f[X+(m<<2)>>2]=j[(f[U>>2]|0)+(d<<1)>>1];m=m+1|0}while(m>>>0 >>0);t=H|(a|0)!=(N|0);r=0;s=w;while(1){q=y|(r|0)==0;n=r<<1;m=(bb(R,V)|0)+g|0;o=m-K|0;p=o>>31;p=p&m|o&~p;if(t){if(q){g=h[1547+(v<<2)+n>>0]|0;m=p*3|0;if((f[F>>2]|0)>>>0<=m>>>0){f[_>>2]=866;f[_+4>>2]=910;f[_+8>>2]=1497;vc(W,812,_)|0;Ub(W)|0}o=(f[E>>2]|0)+(m<<1)|0;f[s>>2]=(j[o>>1]|0)<<16|f[X+(g<<2)>>2];f[s+4>>2]=(j[o+4>>1]|0)<<16|(j[o+2>>1]|0)}o=s+8|0;m=(bb(R,V)|0)+p|0;p=m-K|0;g=p>>31;g=g&m|p&~g;if(q){m=h[(n|1)+(1547+(v<<2))>>0]|0;n=g*3|0;if((f[F>>2]|0)>>>0<=n>>>0){f[Z>>2]=866;f[Z+4>>2]=910;f[Z+8>>2]=1497;vc(W,812,Z)|0;Ub(W)|0}q=(f[E>>2]|0)+(n<<1)|0;f[o>>2]=(j[q>>1]|0)<<16|f[X+(m<<2)>>2];f[s+12>>2]=(j[q+4>>1]|0)<<16|(j[q+2>>1]|0)}}else{if(q){g=h[1547+(v<<2)+n>>0]|0;m=p*3|0;if((f[F>>2]|0)>>>0<=m>>>0){f[$>>2]=866;f[$+4>>2]=910;f[$+8>>2]=1497;vc(W,812,$)|0;Ub(W)|0}q=(f[E>>2]|0)+(m<<1)|0;f[s>>2]=(j[q>>1]|0)<<16|f[X+(g<<2)>>2];f[s+4>>2]=(j[q+4>>1]|0)<<16|(j[q+2>>1]|0)}p=(bb(R,V)|0)+p|0;q=p-K|0;g=q>>31;g=g&p|q&~g}r=r+1|0;if((r|0)==2)break;else s=s+e|0}a=A+a|0;if((a|0)==(x|0))break;else w=w+z|0}}C=C+1|0;if((C|0)==(l|0))break;else B=B+Q|0}}D=D+1|0}while((D|0)!=(L|0));u=aa;return 1}function Za(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;l=a;j=b;k=j;h=c;n=d;i=n;if(!k){g=(e|0)!=0;if(!i){if(g){f[e>>2]=(l>>>0)%(h>>>0);f[e+4>>2]=0}n=0;e=(l>>>0)/(h>>>0)>>>0;return (I=n,e)|0}else{if(!g){n=0;e=0;return (I=n,e)|0}f[e>>2]=a|0;f[e+4>>2]=b&0;n=0;e=0;return (I=n,e)|0}}g=(i|0)==0;do if(h){if(!g){g=(_(i|0)|0)-(_(k|0)|0)|0;if(g>>>0<=31){m=g+1|0;i=31-g|0;b=g-31>>31;h=m;a=l>>>(m>>>0)&b|k<>>(m>>>0)&b;g=0;i=l<>2]=a|0;f[e+4>>2]=j|b&0;n=0;e=0;return (I=n,e)|0}g=h-1|0;if(g&h|0){i=(_(h|0)|0)+33-(_(k|0)|0)|0;p=64-i|0;m=32-i|0;j=m>>31;o=i-32|0;b=o>>31;h=i;a=m-1>>31&k>>>(o>>>0)|(k< >>(i>>>0))&b;b=b&k>>>(i>>>0);g=l< >>(o>>>0))&j|l<
>31;break}if(e|0){f[e>>2]=g&l;f[e+4>>2]=0}if((h|0)==1){o=j|b&0;p=a|0|0;return (I=o,p)|0}else{p=ic(h|0)|0;o=k>>>(p>>>0)|0;p=k<<32-p|l>>>(p>>>0)|0;return (I=o,p)|0}}else{if(g){if(e|0){f[e>>2]=(k>>>0)%(h>>>0);f[e+4>>2]=0}o=0;p=(k>>>0)/(h>>>0)>>>0;return (I=o,p)|0}if(!l){if(e|0){f[e>>2]=0;f[e+4>>2]=(k>>>0)%(i>>>0)}o=0;p=(k>>>0)/(i>>>0)>>>0;return (I=o,p)|0}g=i-1|0;if(!(g&i)){if(e|0){f[e>>2]=a|0;f[e+4>>2]=g&k|b&0}o=0;p=k>>>((ic(i|0)|0)>>>0);return (I=o,p)|0}g=(_(i|0)|0)-(_(k|0)|0)|0;if(g>>>0<=30){b=g+1|0;i=31-g|0;h=b;a=k<>>(b>>>0);b=k>>>(b>>>0);g=0;i=l<>2]=a|0;f[e+4>>2]=j|b&0;o=0;p=0;return (I=o,p)|0}while(0);if(!h){k=i;j=0;i=0}else{m=c|0|0;l=n|d&0;k=Gc(m|0,l|0,-1,-1)|0;c=I;j=i;i=0;do{d=j;j=g>>>31|j<<1;g=i|g<<1;d=a<<1|d>>>31|0;n=a>>>31|b<<1|0;Cc(k|0,c|0,d|0,n|0)|0;p=I;o=p>>31|((p|0)<0?-1:0)<<1;i=o&1;a=Cc(d|0,n|0,o&m|0,(((p|0)<0?-1:0)>>31|((p|0)<0?-1:0)<<1)&l|0)|0;b=I;h=h-1|0}while((h|0)!=0);k=j;j=0}h=0;if(e|0){f[e>>2]=a;f[e+4>>2]=b}o=(g|0)>>>31|(k|h)<<1|(h<<1|g>>>31)&0|j;p=(g<<1|0>>>31)&-2|i;return (I=o,p)|0}function _a(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0;m=a+4|0;l=f[m>>2]|0;c=l&-8;i=a+c|0;if(!(l&3)){if(b>>>0<256){a=0;return a|0}if(c>>>0>=(b+4|0)>>>0?(c-b|0)>>>0<=f[1264]<<1>>>0:0)return a|0;a=0;return a|0}if(c>>>0>=b>>>0){c=c-b|0;if(c>>>0<=15)return a|0;k=a+b|0;f[m>>2]=l&1|b|2;f[k+4>>2]=c|3;m=k+c+4|0;f[m>>2]=f[m>>2]|1;Va(k,c);return a|0}if((i|0)==(f[1150]|0)){k=(f[1147]|0)+c|0;c=k-b|0;d=a+b|0;if(k>>>0<=b>>>0){a=0;return a|0}f[m>>2]=l&1|b|2;f[d+4>>2]=c|1;f[1150]=d;f[1147]=c;return a|0}if((i|0)==(f[1149]|0)){e=(f[1146]|0)+c|0;if(e>>>0>>0){a=0;return a|0}c=e-b|0;d=l&1;if(c>>>0>15){l=a+b|0;k=l+c|0;f[m>>2]=d|b|2;f[l+4>>2]=c|1;f[k>>2]=c;d=k+4|0;f[d>>2]=f[d>>2]&-2;d=l}else{f[m>>2]=d|e|2;d=a+e+4|0;f[d>>2]=f[d>>2]|1;d=0;c=0}f[1146]=c;f[1149]=d;return a|0}d=f[i+4>>2]|0;if(d&2|0){a=0;return a|0}j=(d&-8)+c|0;if(j>>>0>>0){a=0;return a|0}k=j-b|0;e=d>>>3;do if(d>>>0<256){d=f[i+8>>2]|0;c=f[i+12>>2]|0;if((c|0)==(d|0)){f[1144]=f[1144]&~(1< >2]=c;f[c+8>>2]=d;break}}else{h=f[i+24>>2]|0;c=f[i+12>>2]|0;do if((c|0)==(i|0)){e=i+16|0;d=e+4|0;c=f[d>>2]|0;if(!c){c=f[e>>2]|0;if(!c){e=0;break}else g=e}else g=d;while(1){e=c+20|0;d=f[e>>2]|0;if(d|0){c=d;g=e;continue}d=c+16|0;e=f[d>>2]|0;if(!e)break;else{c=e;g=d}}f[g>>2]=0;e=c}else{e=f[i+8>>2]|0;f[e+12>>2]=c;f[c+8>>2]=e;e=c}while(0);if(h|0){c=f[i+28>>2]|0;d=4880+(c<<2)|0;if((i|0)==(f[d>>2]|0)){f[d>>2]=e;if(!e){f[1145]=f[1145]&~(1< >2]|0)!=(i|0)&1)<<2)>>2]=e;if(!e)break}f[e+24>>2]=h;c=i+16|0;d=f[c>>2]|0;if(d|0){f[e+16>>2]=d;f[d+24>>2]=e}c=f[c+4>>2]|0;if(c|0){f[e+20>>2]=c;f[c+24>>2]=e}}}while(0);c=l&1;if(k>>>0<16){f[m>>2]=j|c|2;m=a+j+4|0;f[m>>2]=f[m>>2]|1;return a|0}else{l=a+b|0;f[m>>2]=c|b|2;f[l+4>>2]=k|3;m=l+k+4|0;f[m>>2]=f[m>>2]|1;Va(l,k);return a|0}return 0}function $a(a,b,c,d,e,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;p=u;u=u+592|0;o=p+56|0;j=p+40|0;m=p+72|0;l=p;n=p+68|0;f[l>>2]=40;tb(a,b,l)|0;h=(f[l+4>>2]|0)>>>e;i=(f[l+8>>2]|0)>>>e;l=l+32|0;d=f[l+4>>2]|0;do switch(f[l>>2]|0){case 0:{if(!d)l=8;else k=14;break}case 1:{if(!d)k=13;else k=14;break}case 2:{if(!d)k=13;else k=14;break}case 3:{if(!d)k=13;else k=14;break}case 4:{if(!d)k=13;else k=14;break}case 5:{if(!d)k=13;else k=14;break}case 6:{if(!d)k=13;else k=14;break}case 7:{if(!d)k=13;else k=14;break}case 8:{if(!d)k=13;else k=14;break}case 9:{if(!d)l=8;else k=14;break}case 10:{if(!d)l=8;else k=14;break}default:k=14}while(0);if((k|0)==13)l=16;else if((k|0)==14){f[j>>2]=866;f[j+4>>2]=2672;f[j+8>>2]=1251;vc(m,812,j)|0;Ub(m)|0;l=0}f[n>>2]=c;k=gb(a,b)|0;b=g+e|0;do if(b>>>0>e>>>0){if(!k){d=c;while(1){d=d+(X(X((h+3|0)>>>2,l)|0,(i+3|0)>>>2)|0)|0;e=e+1|0;if((e|0)==(b|0))break;else{i=i>>>1;h=h>>>1}}f[n>>2]=d;break}else{a=i;d=c}while(1){i=X((h+3|0)>>>2,l)|0;j=X(i,(a+3|0)>>>2)|0;if(!(e>>>0>15|j>>>0<8)?(f[k>>2]|0)==519686845:0){wb(k,n,j,i,e)|0;d=f[n>>2]|0}d=d+j|0;f[n>>2]=d;e=e+1|0;if((e|0)==(b|0))break;else{a=a>>>1;h=h>>>1}}}while(0);if(!k){u=p;return}if((f[k>>2]|0)!=519686845){u=p;return}cb(k);if(!(k&7)){Nb(k,0,0,1,0)|0;u=p;return}else{f[o>>2]=866;f[o+4>>2]=2506;f[o+8>>2]=1232;vc(m,812,o)|0;Ub(m)|0;u=p;return}}function ab(a){a=a|0;var c=0,d=0,e=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0;q=u;u=u+576|0;j=q;g=q+64|0;p=q+16|0;e=a+88|0;c=f[e>>2]|0;o=(h[c+39>>0]|0)<<8|(h[c+40>>0]|0);m=a+236|0;i=a+240|0;d=f[i>>2]|0;if((d|0)!=(o|0)){if(d>>>0<=o>>>0){do if((f[a+244>>2]|0)>>>0 >>0){if(fb(m,o,(d+1|0)==(o|0),4,0)|0){c=f[i>>2]|0;break}b[a+248>>0]=1;p=0;u=q;return p|0}else c=d;while(0);Ib((f[m>>2]|0)+(c<<2)|0,0,o-c<<2|0)|0;c=f[e>>2]|0}f[i>>2]=o}n=a+92|0;d=(f[a+4>>2]|0)+((h[c+34>>0]|0)<<8|(h[c+33>>0]|0)<<16|(h[c+35>>0]|0))|0;c=(h[c+37>>0]|0)<<8|(h[c+36>>0]|0)<<16|(h[c+38>>0]|0);if(!c){p=0;u=q;return p|0}f[n>>2]=d;f[a+96>>2]=d;f[a+104>>2]=c;f[a+100>>2]=d+c;f[a+108>>2]=0;f[a+112>>2]=0;k=p+20|0;f[p>>2]=0;f[p+4>>2]=0;f[p+8>>2]=0;f[p+12>>2]=0;b[p+16>>0]=0;l=p+24|0;f[p+44>>2]=0;f[k>>2]=0;f[k+4>>2]=0;f[k+8>>2]=0;f[k+12>>2]=0;f[k+16>>2]=0;b[k+20>>0]=0;if(Pa(n,p)|0?Pa(n,l)|0:0){if(!(f[i>>2]|0)){f[j>>2]=866;f[j+4>>2]=910;f[j+8>>2]=1497;vc(g,812,j)|0;Ub(g)|0}if(!o)c=1;else{j=0;k=0;d=f[m>>2]|0;e=0;a=0;c=0;g=0;i=0;while(1){j=(bb(n,p)|0)+j&31;i=(bb(n,l)|0)+i&63;g=(bb(n,p)|0)+g&31;c=(bb(n,p)|0)+c|0;a=(bb(n,l)|0)+a&63;e=(bb(n,p)|0)+e&31;f[d>>2]=i<<5|j<<11|g|c<<27|a<<21|e<<16;k=k+1|0;if(k>>>0>=o>>>0){c=1;break}else{d=d+4|0;c=c&31}}}}else c=0;Cb(p+24|0);Cb(p);p=c;u=q;return p|0}function bb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,g=0,i=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0;s=u;u=u+576|0;m=s+48|0;o=s+32|0;n=s+16|0;l=s;q=s+64|0;p=f[b+20>>2]|0;r=a+20|0;k=f[r>>2]|0;if((k|0)<24){i=a+4|0;c=f[i>>2]|0;e=f[a+8>>2]|0;d=c>>>0 >>0;if((k|0)<16){if(d){g=(h[c>>0]|0)<<8;c=c+1|0}else g=0;if(c>>>0 >>0){e=h[c>>0]|0;c=c+1|0}else e=0;f[i>>2]=c;f[r>>2]=k+16;d=16;c=e|g}else{if(d){f[i>>2]=c+1;c=h[c>>0]|0}else c=0;f[r>>2]=k+8;d=24}i=a+16|0;e=f[i>>2]|c< >2]=e}else{e=a+16|0;i=e;e=f[e>>2]|0}g=(e>>>16)+1|0;do if(g>>>0<=(f[p+16>>2]|0)>>>0){d=f[(f[p+168>>2]|0)+(e>>>(32-(f[p+8>>2]|0)|0)<<2)>>2]|0;if((d|0)==-1){f[l>>2]=866;f[l+4>>2]=3253;f[l+8>>2]=1393;vc(q,812,l)|0;Ub(q)|0}c=d&65535;d=d>>>16;if((f[b+8>>2]|0)>>>0<=c>>>0){f[n>>2]=866;f[n+4>>2]=909;f[n+8>>2]=1497;vc(q,812,n)|0;Ub(q)|0}if((h[(f[b+4>>2]|0)+c>>0]|0|0)!=(d|0)){f[o>>2]=866;f[o+4>>2]=3257;f[o+8>>2]=1410;vc(q,812,o)|0;Ub(q)|0}}else{d=f[p+20>>2]|0;while(1){c=d+-1|0;if(g>>>0>(f[p+28+(c<<2)>>2]|0)>>>0)d=d+1|0;else break}c=(e>>>(32-d|0))+(f[p+96+(c<<2)>>2]|0)|0;if(c>>>0<(f[b>>2]|0)>>>0){c=j[(f[p+176>>2]|0)+(c<<1)>>1]|0;break}f[m>>2]=866;f[m+4>>2]=3275;f[m+8>>2]=1348;vc(q,812,m)|0;Ub(q)|0;r=0;u=s;return r|0}while(0);f[i>>2]=f[i>>2]< >2]=(f[r>>2]|0)-d;r=c;u=s;return r|0}function cb(a){a=a|0;var c=0,d=0,e=0,g=0,h=0,i=0,j=0,k=0;k=u;u=u+576|0;j=k+48|0;h=k+32|0;g=k+16|0;e=k;i=k+64|0;f[a>>2]=0;c=a+284|0;d=f[c>>2]|0;if(d|0){if(!(d&7))Nb(d,0,0,1,0)|0;else{f[e>>2]=866;f[e+4>>2]=2506;f[e+8>>2]=1232;vc(i,812,e)|0;Ub(i)|0}f[c>>2]=0;f[a+288>>2]=0;f[a+292>>2]=0}b[a+296>>0]=0;c=a+268|0;d=f[c>>2]|0;if(d|0){if(!(d&7))Nb(d,0,0,1,0)|0;else{f[g>>2]=866;f[g+4>>2]=2506;f[g+8>>2]=1232;vc(i,812,g)|0;Ub(i)|0}f[c>>2]=0;f[a+272>>2]=0;f[a+276>>2]=0}b[a+280>>0]=0;c=a+252|0;d=f[c>>2]|0;if(d|0){if(!(d&7))Nb(d,0,0,1,0)|0;else{f[h>>2]=866;f[h+4>>2]=2506;f[h+8>>2]=1232;vc(i,812,h)|0;Ub(i)|0}f[c>>2]=0;f[a+256>>2]=0;f[a+260>>2]=0}b[a+264>>0]=0;c=a+236|0;d=f[c>>2]|0;if(!d){j=a+248|0;b[j>>0]=0;j=a+212|0;Cb(j);j=a+188|0;Cb(j);j=a+164|0;Cb(j);j=a+140|0;Cb(j);j=a+116|0;Cb(j);u=k;return}if(!(d&7))Nb(d,0,0,1,0)|0;else{f[j>>2]=866;f[j+4>>2]=2506;f[j+8>>2]=1232;vc(i,812,j)|0;Ub(i)|0}f[c>>2]=0;f[a+240>>2]=0;f[a+244>>2]=0;j=a+248|0;b[j>>0]=0;j=a+212|0;Cb(j);j=a+188|0;Cb(j);j=a+164|0;Cb(j);j=a+140|0;Cb(j);j=a+116|0;Cb(j);u=k;return}function db(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,g=0.0;a:do if(b>>>0<=20)do switch(b|0){case 9:{d=(f[c>>2]|0)+(4-1)&~(4-1);b=f[d>>2]|0;f[c>>2]=d+4;f[a>>2]=b;break a}case 10:{d=(f[c>>2]|0)+(4-1)&~(4-1);b=f[d>>2]|0;f[c>>2]=d+4;d=a;f[d>>2]=b;f[d+4>>2]=((b|0)<0)<<31>>31;break a}case 11:{d=(f[c>>2]|0)+(4-1)&~(4-1);b=f[d>>2]|0;f[c>>2]=d+4;d=a;f[d>>2]=b;f[d+4>>2]=0;break a}case 12:{d=(f[c>>2]|0)+(8-1)&~(8-1);b=d;e=f[b>>2]|0;b=f[b+4>>2]|0;f[c>>2]=d+8;d=a;f[d>>2]=e;f[d+4>>2]=b;break a}case 13:{e=(f[c>>2]|0)+(4-1)&~(4-1);d=f[e>>2]|0;f[c>>2]=e+4;d=(d&65535)<<16>>16;e=a;f[e>>2]=d;f[e+4>>2]=((d|0)<0)<<31>>31;break a}case 14:{e=(f[c>>2]|0)+(4-1)&~(4-1);d=f[e>>2]|0;f[c>>2]=e+4;e=a;f[e>>2]=d&65535;f[e+4>>2]=0;break a}case 15:{e=(f[c>>2]|0)+(4-1)&~(4-1);d=f[e>>2]|0;f[c>>2]=e+4;d=(d&255)<<24>>24;e=a;f[e>>2]=d;f[e+4>>2]=((d|0)<0)<<31>>31;break a}case 16:{e=(f[c>>2]|0)+(4-1)&~(4-1);d=f[e>>2]|0;f[c>>2]=e+4;e=a;f[e>>2]=d&255;f[e+4>>2]=0;break a}case 17:{e=(f[c>>2]|0)+(8-1)&~(8-1);g=+p[e>>3];f[c>>2]=e+8;p[a>>3]=g;break a}case 18:{e=(f[c>>2]|0)+(8-1)&~(8-1);g=+p[e>>3];f[c>>2]=e+8;p[a>>3]=g;break a}default:break a}while(0);while(0);return}function eb(a){a=a|0;var c=0,e=0,g=0,i=0,j=0,k=0,l=0,m=0,n=0;n=u;u=u+560|0;i=n;g=n+40|0;m=n+16|0;e=f[a+88>>2]|0;k=(h[e+55>>0]|0)<<8|(h[e+56>>0]|0);l=a+92|0;c=(f[a+4>>2]|0)+((h[e+50>>0]|0)<<8|(h[e+49>>0]|0)<<16|(h[e+51>>0]|0))|0;e=(h[e+53>>0]|0)<<8|(h[e+52>>0]|0)<<16|(h[e+54>>0]|0);if(!e){m=0;u=n;return m|0}f[l>>2]=c;f[a+96>>2]=c;f[a+104>>2]=e;f[a+100>>2]=c+e;f[a+108>>2]=0;f[a+112>>2]=0;f[m+20>>2]=0;f[m>>2]=0;f[m+4>>2]=0;f[m+8>>2]=0;f[m+12>>2]=0;b[m+16>>0]=0;a:do if(Pa(l,m)|0){j=a+268|0;e=a+272|0;c=f[e>>2]|0;if((c|0)!=(k|0)){if(c>>>0<=k>>>0){do if((f[a+276>>2]|0)>>>0 >>0)if(fb(j,k,(c+1|0)==(k|0),2,0)|0){c=f[e>>2]|0;break}else{b[a+280>>0]=1;c=0;break a}while(0);Ib((f[j>>2]|0)+(c<<1)|0,0,k-c<<1|0)|0}f[e>>2]=k}if(!k){f[i>>2]=866;f[i+4>>2]=910;f[i+8>>2]=1497;vc(g,812,i)|0;Ub(g)|0;c=1;break}e=0;a=0;g=0;c=f[j>>2]|0;while(1){j=bb(l,m)|0;g=j+g&255;a=(bb(l,m)|0)+a&255;d[c>>1]=a<<8|g;e=e+1|0;if(e>>>0>=k>>>0){c=1;break}else c=c+2|0}}else c=0;while(0);Cb(m);m=c;u=n;return m|0}function fb(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;p=u;u=u+576|0;m=p+48|0;j=p+32|0;h=p+16|0;g=p;l=p+64|0;n=p+60|0;k=a+4|0;o=a+8|0;if((f[k>>2]|0)>>>0>(f[o>>2]|0)>>>0){f[g>>2]=866;f[g+4>>2]=2123;f[g+8>>2]=845;vc(l,812,g)|0;Ub(l)|0}if((2147418112/(d>>>0)|0)>>>0<=b>>>0){f[h>>2]=866;f[h+4>>2]=2124;f[h+8>>2]=885;vc(l,812,h)|0;Ub(l)|0}g=f[o>>2]|0;if(g>>>0>=b>>>0){o=1;u=p;return o|0}if(c?(i=b+-1|0,(i&b|0)!=0):0){b=i>>>16|i;b=b>>>8|b;b=b>>>4|b;b=b>>>2|b;b=(b>>>1|b)+1|0;if(!b){b=0;c=10}else c=9}else c=9;if((c|0)==9)if(b>>>0<=g>>>0)c=10;if((c|0)==10){f[j>>2]=866;f[j+4>>2]=2133;f[j+8>>2]=933;vc(l,812,j)|0;Ub(l)|0}i=X(b,d)|0;if(!e){g=Gb(f[a>>2]|0,i,n,1)|0;if(!g)b=0;else{f[a>>2]=g;c=20}}else{h=Db(i,n)|0;if(!h)b=0;else{Ia[e&0](h,f[a>>2]|0,f[k>>2]|0);g=f[a>>2]|0;do if(g|0)if(!(g&7)){Nb(g,0,0,1,0)|0;break}else{f[m>>2]=866;f[m+4>>2]=2506;f[m+8>>2]=1232;vc(l,812,m)|0;Ub(l)|0;break}while(0);f[a>>2]=h;c=20}}if((c|0)==20){g=f[n>>2]|0;if(g>>>0>i>>>0)b=(g>>>0)/(d>>>0)|0;f[o>>2]=b;b=1}o=b;u=p;return o|0}function gb(a,c){a=a|0;c=c|0;var d=0,e=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;o=u;u=u+528|0;m=o;j=o+16|0;if((a|0)==0|c>>>0<62){p=0;u=o;return p|0}k=Db(300,0)|0;if(!k){p=0;u=o;return p|0}f[k>>2]=519686845;f[k+4>>2]=0;f[k+8>>2]=0;l=k+88|0;d=k+136|0;e=k+160|0;g=k+184|0;h=k+208|0;i=k+232|0;n=k+252|0;f[n>>2]=0;f[n+4>>2]=0;f[n+8>>2]=0;b[n+12>>0]=0;n=k+268|0;f[n>>2]=0;f[n+4>>2]=0;f[n+8>>2]=0;b[n+12>>0]=0;n=k+284|0;f[n>>2]=0;f[n+4>>2]=0;f[n+8>>2]=0;b[n+12>>0]=0;n=l;p=n+44|0;do{f[n>>2]=0;n=n+4|0}while((n|0)<(p|0));b[l+44>>0]=0;f[d>>2]=0;f[d+4>>2]=0;f[d+8>>2]=0;f[d+12>>2]=0;f[d+16>>2]=0;b[d+20>>0]=0;f[e>>2]=0;f[e+4>>2]=0;f[e+8>>2]=0;f[e+12>>2]=0;f[e+16>>2]=0;b[e+20>>0]=0;f[g>>2]=0;f[g+4>>2]=0;f[g+8>>2]=0;f[g+12>>2]=0;f[g+16>>2]=0;b[g+20>>0]=0;f[h>>2]=0;f[h+4>>2]=0;f[h+8>>2]=0;f[h+12>>2]=0;f[h+16>>2]=0;b[h+20>>0]=0;f[i>>2]=0;f[i+4>>2]=0;f[i+8>>2]=0;f[i+12>>2]=0;b[i+16>>0]=0;if(xb(k,a,c)|0){p=k;u=o;return p|0}cb(k);if(!(k&7)){Nb(k,0,0,1,0)|0;p=0;u=o;return p|0}else{f[m>>2]=866;f[m+4>>2]=2506;f[m+8>>2]=1232;vc(j,812,m)|0;Ub(j)|0;p=0;u=o;return p|0}return 0}function hb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,g=0,h=0,i=0,j=0;i=u;u=u+576|0;g=i+40|0;e=i+56|0;j=i;f[j>>2]=40;tb(a,b,j)|0;d=(((f[j+4>>2]|0)>>>c)+3|0)>>>2;b=(((f[j+8>>2]|0)>>>c)+3|0)>>>2;c=j+32|0;a=f[c+4>>2]|0;do switch(f[c>>2]|0){case 0:{if(!a)a=8;else h=14;break}case 1:{if(!a)h=13;else h=14;break}case 2:{if(!a)h=13;else h=14;break}case 3:{if(!a)h=13;else h=14;break}case 4:{if(!a)h=13;else h=14;break}case 5:{if(!a)h=13;else h=14;break}case 6:{if(!a)h=13;else h=14;break}case 7:{if(!a)h=13;else h=14;break}case 8:{if(!a)h=13;else h=14;break}case 9:{if(!a)a=8;else h=14;break}case 10:{if(!a)a=8;else h=14;break}default:h=14}while(0);if((h|0)==13)a=16;else if((h|0)==14){f[g>>2]=866;f[g+4>>2]=2672;f[g+8>>2]=1251;vc(e,812,g)|0;Ub(e)|0;a=0}j=X(X(b,d)|0,a)|0;u=i;return j|0}function ib(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,g=0;e=u;u=u+576|0;d=e+40|0;c=e+56|0;g=e;f[g>>2]=40;tb(a,b,g)|0;b=g+32|0;a=f[b+4>>2]|0;do switch(f[b>>2]|0){case 0:{if(!a){g=8;u=e;return g|0}else a=14;break}case 1:{if(!a)a=13;else a=14;break}case 2:{if(!a)a=13;else a=14;break}case 3:{if(!a)a=13;else a=14;break}case 4:{if(!a)a=13;else a=14;break}case 5:{if(!a)a=13;else a=14;break}case 6:{if(!a)a=13;else a=14;break}case 7:{if(!a)a=13;else a=14;break}case 8:{if(!a)a=13;else a=14;break}case 9:{if(!a){g=8;u=e;return g|0}else a=14;break}case 10:{if(!a){g=8;u=e;return g|0}else a=14;break}default:a=14}while(0);if((a|0)==13){g=16;u=e;return g|0}else if((a|0)==14){f[d>>2]=866;f[d+4>>2]=2672;f[d+8>>2]=1251;vc(c,812,d)|0;Ub(c)|0;g=0;u=e;return g|0}return 0}function jb(a,c,d,e,g,i,j){a=a|0;c=c|0;d=d|0;e=e|0;g=g|0;i=i|0;j=j|0;var k=0,l=0,m=0,n=0;n=f[a+88>>2]|0;l=(h[n+12>>0]<<8|h[n+13>>0])>>>j;m=(h[n+14>>0]<<8|h[n+15>>0])>>>j;l=((l>>>0>1?l:1)+3|0)>>>2;m=((m>>>0>1?m:1)+3|0)>>>2;n=n+18|0;j=b[n>>0]|0;j=X(l,j<<24>>24==0|j<<24>>24==9?8:16)|0;if(i)if((i&3|0)==0&j>>>0<=i>>>0)j=i;else{g=0;return g|0}if((X(j,m)|0)>>>0>g>>>0){g=0;return g|0}i=(l+1|0)>>>1;k=(m+1|0)>>>1;if(!d){g=0;return g|0}f[a+92>>2]=c;f[a+96>>2]=c;f[a+104>>2]=d;f[a+100>>2]=c+d;f[a+108>>2]=0;f[a+112>>2]=0;switch(b[n>>0]|0){case 0:{if(!(Ra(a,e,g,j,l,m,i,k)|0)){g=0;return g|0}break}case 4:case 6:case 5:case 3:case 2:{if(!(Ua(a,e,g,j,l,m,i,k)|0)){g=0;return g|0}break}case 9:{if(!(Ya(a,e,g,j,l,m,i,k)|0)){g=0;return g|0}break}case 8:case 7:{if(!(Sa(a,e,g,j,l,m,i,k)|0)){g=0;return g|0}break}default:{g=0;return g|0}}g=1;return g|0}function kb(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,g=0,h=0;if((d|0)>=8192)return va(a|0,c|0,d|0)|0;h=a|0;g=a+d|0;if((a&3)==(c&3)){while(a&3){if(!d)return h|0;b[a>>0]=b[c>>0]|0;a=a+1|0;c=c+1|0;d=d-1|0}d=g&-4|0;e=d-64|0;while((a|0)<=(e|0)){f[a>>2]=f[c>>2];f[a+4>>2]=f[c+4>>2];f[a+8>>2]=f[c+8>>2];f[a+12>>2]=f[c+12>>2];f[a+16>>2]=f[c+16>>2];f[a+20>>2]=f[c+20>>2];f[a+24>>2]=f[c+24>>2];f[a+28>>2]=f[c+28>>2];f[a+32>>2]=f[c+32>>2];f[a+36>>2]=f[c+36>>2];f[a+40>>2]=f[c+40>>2];f[a+44>>2]=f[c+44>>2];f[a+48>>2]=f[c+48>>2];f[a+52>>2]=f[c+52>>2];f[a+56>>2]=f[c+56>>2];f[a+60>>2]=f[c+60>>2];a=a+64|0;c=c+64|0}while((a|0)<(d|0)){f[a>>2]=f[c>>2];a=a+4|0;c=c+4|0}}else{d=g-4|0;while((a|0)<(d|0)){b[a>>0]=b[c>>0]|0;b[a+1>>0]=b[c+1>>0]|0;b[a+2>>0]=b[c+2>>0]|0;b[a+3>>0]=b[c+3>>0]|0;a=a+4|0;c=c+4|0}}while((a|0)<(g|0)){b[a>>0]=b[c>>0]|0;a=a+1|0;c=c+1|0}return h|0}function lb(a){a=a|0;var b=0,c=0,d=0,e=0;e=a+92|0;d=a+88|0;c=f[d>>2]|0;b=(f[a+4>>2]|0)+((h[c+68>>0]|0)<<8|(h[c+67>>0]|0)<<16|(h[c+69>>0]|0))|0;c=(h[c+65>>0]|0)<<8|(h[c+66>>0]|0);if(!c){e=0;return e|0}f[e>>2]=b;f[a+96>>2]=b;f[a+104>>2]=c;f[a+100>>2]=b+c;f[a+108>>2]=0;f[a+112>>2]=0;if(!(Pa(e,a+116|0)|0)){e=0;return e|0}b=f[d>>2]|0;do if(!((h[b+39>>0]|0)<<8|(h[b+40>>0]|0))){if(!((h[b+55>>0]|0)<<8|(h[b+56>>0]|0))){e=0;return e|0}}else{if(!(Pa(e,a+140|0)|0)){e=0;return e|0}if(Pa(e,a+188|0)|0){b=f[d>>2]|0;break}else{e=0;return e|0}}while(0);if((h[b+55>>0]|0)<<8|(h[b+56>>0]|0)|0){if(!(Pa(e,a+164|0)|0)){e=0;return e|0}if(!(Pa(e,a+212|0)|0)){e=0;return e|0}}e=1;return e|0}function mb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;m=u;u=u+48|0;k=m+16|0;g=m;e=m+32|0;i=a+28|0;d=f[i>>2]|0;f[e>>2]=d;j=a+20|0;d=(f[j>>2]|0)-d|0;f[e+4>>2]=d;f[e+8>>2]=b;f[e+12>>2]=c;d=d+c|0;h=a+60|0;f[g>>2]=f[h>>2];f[g+4>>2]=e;f[g+8>>2]=2;g=Ic(Aa(146,g|0)|0)|0;a:do if((d|0)!=(g|0)){b=2;while(1){if((g|0)<0)break;d=d-g|0;o=f[e+4>>2]|0;n=g>>>0>o>>>0;e=n?e+8|0:e;b=(n<<31>>31)+b|0;o=g-(n?o:0)|0;f[e>>2]=(f[e>>2]|0)+o;n=e+4|0;f[n>>2]=(f[n>>2]|0)-o;f[k>>2]=f[h>>2];f[k+4>>2]=e;f[k+8>>2]=b;g=Ic(Aa(146,k|0)|0)|0;if((d|0)==(g|0)){l=3;break a}}f[a+16>>2]=0;f[i>>2]=0;f[j>>2]=0;f[a>>2]=f[a>>2]|32;if((b|0)==2)c=0;else c=c-(f[e+4>>2]|0)|0}else l=3;while(0);if((l|0)==3){o=f[a+44>>2]|0;f[a+16>>2]=o+(f[a+48>>2]|0);f[i>>2]=o;f[j>>2]=o}u=m;return c|0}function nb(a,c,d,e,g){a=a|0;c=c|0;d=d|0;e=e|0;g=g|0;var h=0,i=0,j=0,k=0;do if(!(Sc(a,f[c+8>>2]|0,g)|0)){h=a+8|0;if(!(Sc(a,f[c>>2]|0,g)|0)){j=f[h>>2]|0;Fa[f[(f[j>>2]|0)+24>>2]&3](j,c,d,e,g);break}a=c+32|0;if((f[c+16>>2]|0)!=(d|0)?(i=c+20|0,(f[i>>2]|0)!=(d|0)):0){f[a>>2]=e;e=c+44|0;if((f[e>>2]|0)==4)break;a=c+52|0;b[a>>0]=0;k=c+53|0;b[k>>0]=0;h=f[h>>2]|0;Ka[f[(f[h>>2]|0)+20>>2]&3](h,c,d,d,1,g);if(b[k>>0]|0)if(!(b[a>>0]|0)){a=3;j=11}else a=3;else{a=4;j=11}if((j|0)==11){f[i>>2]=d;k=c+40|0;f[k>>2]=(f[k>>2]|0)+1;if((f[c+36>>2]|0)==1?(f[c+24>>2]|0)==2:0)b[c+54>>0]=1}f[e>>2]=a;break}if((e|0)==1)f[a>>2]=1}else jc(0,c,d,e);while(0);return}function ob(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0;r=u;u=u+224|0;m=r+120|0;n=r+80|0;p=r;q=r+136|0;e=n;g=e+40|0;do{f[e>>2]=0;e=e+4|0}while((e|0)<(g|0));f[m>>2]=f[d>>2];if((Oa(0,c,m,p,n)|0)<0)d=-1;else{if((f[a+76>>2]|0)>-1)o=td(a)|0;else o=0;d=f[a>>2]|0;l=d&32;if((b[a+74>>0]|0)<1)f[a>>2]=d&-33;e=a+48|0;if(!(f[e>>2]|0)){g=a+44|0;h=f[g>>2]|0;f[g>>2]=q;i=a+28|0;f[i>>2]=q;j=a+20|0;f[j>>2]=q;f[e>>2]=80;k=a+16|0;f[k>>2]=q+80;d=Oa(a,c,m,p,n)|0;if(h){Ea[f[a+36>>2]&7](a,0,0)|0;d=(f[j>>2]|0)==0?-1:d;f[g>>2]=h;f[e>>2]=0;f[k>>2]=0;f[i>>2]=0;f[j>>2]=0}}else d=Oa(a,c,m,p,n)|0;e=f[a>>2]|0;f[a>>2]=e|l;if(o|0)sd(a);d=(e&32|0)==0?d:-1}u=r;return d|0}function pb(a,c,e,g){a=a|0;c=c|0;e=e|0;g=g|0;var h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0;p=u;u=u+64|0;n=p;m=f[a>>2]|0;o=a+(f[m+-8>>2]|0)|0;m=f[m+-4>>2]|0;f[n>>2]=e;f[n+4>>2]=a;f[n+8>>2]=c;f[n+12>>2]=g;a=n+16|0;c=n+20|0;g=n+24|0;h=n+28|0;i=n+32|0;j=n+40|0;k=a;l=k+36|0;do{f[k>>2]=0;k=k+4|0}while((k|0)<(l|0));d[a+36>>1]=0;b[a+38>>0]=0;a:do if(Sc(m,e,0)|0){f[n+48>>2]=1;Ka[f[(f[m>>2]|0)+20>>2]&3](m,n,o,o,1,0);a=(f[g>>2]|0)==1?o:0}else{Fa[f[(f[m>>2]|0)+24>>2]&3](m,n,o,1,0);switch(f[n+36>>2]|0){case 0:{a=(f[j>>2]|0)==1&(f[h>>2]|0)==1&(f[i>>2]|0)==1?f[c>>2]|0:0;break a}case 1:break;default:{a=0;break a}}if((f[g>>2]|0)!=1?!((f[j>>2]|0)==0&(f[h>>2]|0)==1&(f[i>>2]|0)==1):0){a=0;break}a=f[a>>2]|0}while(0);u=p;return a|0}function qb(a){a=a|0;var b=0,c=0,d=0,e=0,g=0,h=0,i=0,j=0;j=u;u=u+544|0;h=j+16|0;b=j;e=j+32|0;g=a+8|0;c=f[g>>2]|0;if((c+-1|0)>>>0>=8192){f[b>>2]=866;f[b+4>>2]=3006;f[b+8>>2]=1257;vc(e,812,b)|0;Ub(e)|0}f[a>>2]=c;d=a+20|0;b=f[d>>2]|0;if(!b){b=Db(180,0)|0;if(!b)b=0;else{i=b+164|0;f[i>>2]=0;f[i+4>>2]=0;f[i+8>>2]=0;f[i+12>>2]=0}f[d>>2]=b;i=f[a>>2]|0}else i=c;if(!(f[g>>2]|0)){f[h>>2]=866;f[h+4>>2]=910;f[h+8>>2]=1497;vc(e,812,h)|0;Ub(e)|0;h=f[a>>2]|0}else h=i;e=f[a+4>>2]|0;if(h>>>0>16){c=h;d=0}else{a=0;a=Qa(b,i,e,a)|0;u=j;return a|0}while(1){g=d+1|0;if(c>>>0>3){c=c>>>1;d=g}else break}a=d+2+((g|0)!=32&1< >>0 >>0&1)|0;a=(a>>>0<11?a:11)&255;a=Qa(b,i,e,a)|0;u=j;return a|0}function rb(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,g=0,h=0,i=0,j=0,k=0,l=0,m=0,n=0,o=0;o=(f[a>>2]|0)+1794895138|0;h=Tc(f[a+8>>2]|0,o)|0;e=Tc(f[a+12>>2]|0,o)|0;g=Tc(f[a+16>>2]|0,o)|0;a:do if((h>>>0 >>2>>>0?(n=c-(h<<2)|0,e>>>0 >>0&g>>>0 >>0):0)?((g|e)&3|0)==0:0){n=e>>>2;m=g>>>2;l=0;while(1){j=h>>>1;k=l+j|0;i=k<<1;g=i+n|0;e=Tc(f[a+(g<<2)>>2]|0,o)|0;g=Tc(f[a+(g+1<<2)>>2]|0,o)|0;if(!(g>>>0 >>0&e>>>0<(c-g|0)>>>0)){e=0;break a}if(b[a+(g+e)>>0]|0){e=0;break a}e=_b(d,a+g|0)|0;if(!e)break;e=(e|0)<0;if((h|0)==1){e=0;break a}else{l=e?l:k;h=e?j:h-j|0}}e=i+m|0;g=Tc(f[a+(e<<2)>>2]|0,o)|0;e=Tc(f[a+(e+1<<2)>>2]|0,o)|0;if(e>>>0 >>0&g>>>0<(c-e|0)>>>0)e=(b[a+(e+g)>>0]|0)==0?a+e|0:0;else e=0}else e=0;while(0);return e|0}function sb(a){a=a|0;var b=0,c=0,d=0,e=0,g=0,h=0,i=0,j=0;i=u;u=u+576|0;g=i+48|0;h=i+32|0;d=i+16|0;c=i;e=i+64|0;b=f[a+168>>2]|0;do if(b|0){j=f[b+-4>>2]|0;b=b+-8|0;if(!((j|0)!=0?(j|0)==(~f[b>>2]|0):0)){f[c>>2]=866;f[c+4>>2]=651;f[c+8>>2]=1579;vc(e,812,c)|0;Ub(e)|0}if(!(b&7)){Nb(b,0,0,1,0)|0;break}else{f[d>>2]=866;f[d+4>>2]=2506;f[d+8>>2]=1232;vc(e,812,d)|0;Ub(e)|0;break}}while(0);b=f[a+176>>2]|0;if(!b){u=i;return}j=f[b+-4>>2]|0;b=b+-8|0;if(!((j|0)!=0?(j|0)==(~f[b>>2]|0):0)){f[h>>2]=866;f[h+4>>2]=651;f[h+8>>2]=1579;vc(e,812,h)|0;Ub(e)|0}if(!(b&7)){Nb(b,0,0,1,0)|0;u=i;return}else{f[g>>2]=866;f[g+4>>2]=2506;f[g+8>>2]=1232;vc(e,812,g)|0;Ub(e)|0;u=i;return}}function tb(a,c,d){a=a|0;c=c|0;d=d|0;var e=0;if(!((a|0)!=0&c>>>0>73&(d|0)!=0)){d=0;return d|0}if((f[d>>2]|0)!=40){d=0;return d|0}if(((h[a>>0]|0)<<8|(h[a+1>>0]|0)|0)!=18552){d=0;return d|0}if(((h[a+2>>0]|0)<<8|(h[a+3>>0]|0))>>>0<74){d=0;return d|0}if(((h[a+7>>0]|0)<<16|(h[a+6>>0]|0)<<24|(h[a+8>>0]|0)<<8|(h[a+9>>0]|0))>>>0>c>>>0){d=0;return d|0}f[d+4>>2]=(h[a+12>>0]|0)<<8|(h[a+13>>0]|0);f[d+8>>2]=(h[a+14>>0]|0)<<8|(h[a+15>>0]|0);f[d+12>>2]=h[a+16>>0];f[d+16>>2]=h[a+17>>0];c=a+18|0;e=d+32|0;f[e>>2]=h[c>>0];f[e+4>>2]=0;c=b[c>>0]|0;f[d+20>>2]=c<<24>>24==0|c<<24>>24==9?8:16;f[d+24>>2]=(h[a+26>>0]|0)<<16|(h[a+25>>0]|0)<<24|(h[a+27>>0]|0)<<8|(h[a+28>>0]|0);f[d+28>>2]=(h[a+30>>0]|0)<<16|(h[a+29>>0]|0)<<24|(h[a+31>>0]|0)<<8|(h[a+32>>0]|0);d=1;return d|0}function ub(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,g=0,i=0,j=0,k=0,l=0;l=u;u=u+544|0;j=l+16|0;c=l;i=l+32|0;if(b>>>0>=33){f[c>>2]=866;f[c+4>>2]=3199;f[c+8>>2]=1350;vc(i,812,c)|0;Ub(i)|0}k=a+20|0;c=f[k>>2]|0;if((c|0)>=(b|0)){e=a+16|0;g=e;e=f[e>>2]|0;i=c;j=32-b|0;j=e>>>j;e=e<>2]=e;b=i-b|0;f[k>>2]=b;u=l;return j|0}e=a+4|0;g=a+8|0;d=a+16|0;do{a=f[e>>2]|0;if((a|0)==(f[g>>2]|0))a=0;else{f[e>>2]=a+1;a=h[a>>0]|0}c=c+8|0;f[k>>2]=c;if((c|0)>=33){f[j>>2]=866;f[j+4>>2]=3208;f[j+8>>2]=1366;vc(i,812,j)|0;Ub(i)|0;c=f[k>>2]|0}a=a<<32-c|f[d>>2];f[d>>2]=a}while((c|0)<(b|0));j=32-b|0;j=a>>>j;i=a<>2]=i;b=c-b|0;f[k>>2]=b;u=l;return j|0}function vb(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,g=0,h=0,i=0;h=c&255;e=(d|0)!=0;a:do if(e&(a&3|0)!=0){g=c&255;while(1){if((b[a>>0]|0)==g<<24>>24){i=6;break a}a=a+1|0;d=d+-1|0;e=(d|0)!=0;if(!(e&(a&3|0)!=0)){i=5;break}}}else i=5;while(0);if((i|0)==5)if(e)i=6;else d=0;b:do if((i|0)==6){g=c&255;if((b[a>>0]|0)!=g<<24>>24){e=X(h,16843009)|0;c:do if(d>>>0>3)while(1){h=f[a>>2]^e;if((h&-2139062144^-2139062144)&h+-16843009|0)break;a=a+4|0;d=d+-4|0;if(d>>>0<=3){i=11;break c}}else i=11;while(0);if((i|0)==11)if(!d){d=0;break}while(1){if((b[a>>0]|0)==g<<24>>24)break b;a=a+1|0;d=d+-1|0;if(!d){d=0;break}}}}while(0);return (d|0?a:0)|0}function wb(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var g=0,i=0,j=0,k=0,l=0,m=0;m=u;u=u+528|0;l=m;k=m+16|0;i=f[a+88>>2]|0;j=(h[i+70+(e<<2)+1>>0]|0)<<16|(h[i+70+(e<<2)>>0]|0)<<24|(h[i+70+(e<<2)+2>>0]|0)<<8|(h[i+70+(e<<2)+3>>0]|0);g=e+1|0;if(g>>>0<(h[i+16>>0]|0)>>>0)g=(h[i+70+(g<<2)+1>>0]|0)<<16|(h[i+70+(g<<2)>>0]|0)<<24|(h[i+70+(g<<2)+2>>0]|0)<<8|(h[i+70+(g<<2)+3>>0]|0);else g=f[a+8>>2]|0;if(g>>>0>j>>>0){k=a+4|0;k=f[k>>2]|0;k=k+j|0;l=g-j|0;l=jb(a,k,l,b,c,d,e)|0;u=m;return l|0}f[l>>2]=866;f[l+4>>2]=3694;f[l+8>>2]=1508;vc(k,812,l)|0;Ub(k)|0;k=a+4|0;k=f[k>>2]|0;k=k+j|0;l=g-j|0;l=jb(a,k,l,b,c,d,e)|0;u=m;return l|0}function xb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;if(((!((b|0)==0|c>>>0<74)?((h[b>>0]|0)<<8|(h[b+1>>0]|0)|0)==18552:0)?((h[b+2>>0]|0)<<8|(h[b+3>>0]|0))>>>0>=74:0)?((h[b+7>>0]|0)<<16|(h[b+6>>0]|0)<<24|(h[b+8>>0]|0)<<8|(h[b+9>>0]|0))>>>0<=c>>>0:0){d=a+88|0;f[d>>2]=b;f[a+4>>2]=b;f[a+8>>2]=c;if(!(lb(a)|0)){e=0;return e|0}b=f[d>>2]|0;if((h[b+39>>0]|0)<<8|(h[b+40>>0]|0)){if(ab(a)|0?Xa(a)|0:0){b=f[d>>2]|0;e=11}}else e=11;if((e|0)==11){if(!((h[b+55>>0]|0)<<8|(h[b+56>>0]|0))){e=1;return e|0}if(eb(a)|0?Wa(a)|0:0){e=1;return e|0}}e=0;return e|0}f[a+88>>2]=0;e=0;return e|0}function yb(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,g=0,i=0,j=0,k=0,l=0;l=u;u=u+528|0;i=l;g=l+16|0;if(!b){k=0;u=l;return k|0}if(b>>>0<=16){k=ub(a,b)|0;u=l;return k|0}j=ub(a,b+-16|0)|0;k=a+20|0;b=f[k>>2]|0;if((b|0)<16){d=a+4|0;e=a+8|0;c=a+16|0;do{a=f[d>>2]|0;if((a|0)==(f[e>>2]|0))a=0;else{f[d>>2]=a+1;a=h[a>>0]|0}b=b+8|0;f[k>>2]=b;if((b|0)>=33){f[i>>2]=866;f[i+4>>2]=3208;f[i+8>>2]=1366;vc(g,812,i)|0;Ub(g)|0;b=f[k>>2]|0}a=a<<32-b|f[c>>2];f[c>>2]=a}while((b|0)<16)}else{a=a+16|0;c=a;a=f[a>>2]|0}f[c>>2]=a<<16;f[k>>2]=b+-16;k=a>>>16|j<<16;u=l;return k|0}function zb(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,g=0,h=0,i=0,j=0;e=d+16|0;g=f[e>>2]|0;if(!g)if(!(Zb(d)|0)){g=f[e>>2]|0;h=5}else e=0;else h=5;a:do if((h|0)==5){j=d+20|0;i=f[j>>2]|0;e=i;if((g-i|0)>>>0 >>0){e=Ea[f[d+36>>2]&7](d,a,c)|0;break}b:do if((b[d+75>>0]|0)>-1){i=c;while(1){if(!i){h=0;g=a;break b}g=i+-1|0;if((b[a+g>>0]|0)==10)break;else i=g}e=Ea[f[d+36>>2]&7](d,a,i)|0;if(e>>>0>>0)break a;h=i;g=a+i|0;c=c-i|0;e=f[j>>2]|0}else{h=0;g=a}while(0);kb(e|0,g|0,c|0)|0;f[j>>2]=(f[j>>2]|0)+c;e=h+c|0}while(0);return e|0}function Ab(a,c,d){a=a|0;c=c|0;d=d|0;do if(a){if(c>>>0<128){b[a>>0]=c;a=1;break}d=(ld()|0)+188|0;if(!(f[f[d>>2]>>2]|0))if((c&-128|0)==57216){b[a>>0]=c;a=1;break}else{a=jd()|0;f[a>>2]=84;a=-1;break}if(c>>>0<2048){b[a>>0]=c>>>6|192;b[a+1>>0]=c&63|128;a=2;break}if(c>>>0<55296|(c&-8192|0)==57344){b[a>>0]=c>>>12|224;b[a+1>>0]=c>>>6&63|128;b[a+2>>0]=c&63|128;a=3;break}if((c+-65536|0)>>>0<1048576){b[a>>0]=c>>>18|240;b[a+1>>0]=c>>>12&63|128;b[a+2>>0]=c>>>6&63|128;b[a+3>>0]=c&63|128;a=4;break}else{a=jd()|0;f[a>>2]=84;a=-1;break}}else a=1;while(0);return a|0}function Bb(){var a=0,b=0,c=0,d=0,e=0,g=0,h=0,i=0;e=u;u=u+48|0;h=e+32|0;c=e+24|0;i=e+16|0;g=e;e=e+36|0;a=rc()|0;if(a|0?(d=f[a>>2]|0,d|0):0){a=d+48|0;b=f[a>>2]|0;a=f[a+4>>2]|0;if(!((b&-256|0)==1126902528&(a|0)==1129074247)){f[c>>2]=4168;Ac(4118,c)}if((b|0)==1126902529&(a|0)==1129074247)a=f[d+44>>2]|0;else a=d+80|0;f[e>>2]=a;d=f[d>>2]|0;a=f[d+4>>2]|0;if(Ea[f[(f[2]|0)+16>>2]&7](8,d,e)|0){i=f[e>>2]|0;i=Ha[f[(f[i>>2]|0)+8>>2]&1](i)|0;f[g>>2]=4168;f[g+4>>2]=a;f[g+8>>2]=i;Ac(4032,g)}else{f[i>>2]=4168;f[i+4>>2]=a;Ac(4077,i)}}Ac(4156,h)}function Cb(a){a=a|0;var c=0,d=0,e=0,g=0,h=0;h=u;u=u+544|0;g=h+16|0;d=h;e=h+32|0;c=f[a+20>>2]|0;do if(c|0){sb(c);if(!(c&7)){Nb(c,0,0,1,0)|0;break}else{f[d>>2]=866;f[d+4>>2]=2506;f[d+8>>2]=1232;vc(e,812,d)|0;Ub(e)|0;break}}while(0);c=a+4|0;d=f[c>>2]|0;if(!d){g=a+16|0;b[g>>0]=0;u=h;return}if(!(d&7))Nb(d,0,0,1,0)|0;else{f[g>>2]=866;f[g+4>>2]=2506;f[g+8>>2]=1232;vc(e,812,g)|0;Ub(e)|0}f[c>>2]=0;f[a+8>>2]=0;f[a+12>>2]=0;g=a+16|0;b[g>>0]=0;u=h;return}function Db(a,b){a=a|0;b=b|0;var c=0,d=0,e=0,g=0,h=0,i=0,j=0;j=u;u=u+560|0;i=j+32|0;h=j+16|0;c=j;g=j+48|0;e=j+44|0;d=a+3&-4;d=d|0?d:4;if(d>>>0>2147418112){f[c>>2]=866;f[c+4>>2]=2506;f[c+8>>2]=1103;vc(g,812,c)|0;Ub(g)|0;i=0;u=j;return i|0}f[e>>2]=d;a=Nb(0,d,e,1,0)|0;c=f[e>>2]|0;if(b|0)f[b>>2]=c;if(!((a|0)==0|c>>>0 >>0)){if(a&7){f[i>>2]=866;f[i+4>>2]=2533;f[i+8>>2]=1156;vc(g,812,i)|0;Ub(g)|0}}else{f[h>>2]=866;f[h+4>>2]=2506;f[h+8>>2]=1129;vc(g,812,h)|0;Ub(g)|0;a=0}i=a;u=j;return i|0}function Eb(a){a=a|0;var c=0,d=0,e=0,g=0,h=0,i=0;i=u;u=u+544|0;h=i+16|0;e=i;g=i+32|0;f[a>>2]=0;c=a+4|0;d=f[c>>2]|0;if(d|0){if(!(d&7))Nb(d,0,0,1,0)|0;else{f[e>>2]=866;f[e+4>>2]=2506;f[e+8>>2]=1232;vc(g,812,e)|0;Ub(g)|0}f[c>>2]=0;f[a+8>>2]=0;f[a+12>>2]=0}b[a+16>>0]=0;a=a+20|0;c=f[a>>2]|0;if(!c){u=i;return}sb(c);if(!(c&7))Nb(c,0,0,1,0)|0;else{f[h>>2]=866;f[h+4>>2]=2506;f[h+8>>2]=1232;vc(g,812,h)|0;Ub(g)|0}f[a>>2]=0;u=i;return}function Fb(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;var g=0,h=0,i=0,j=0,k=0,l=0,m=0;m=u;u=u+128|0;g=m+124|0;l=m;h=l;i=604;j=h+124|0;do{f[h>>2]=f[i>>2];h=h+4|0;i=i+4|0}while((h|0)<(j|0));if((c+-1|0)>>>0>2147483646)if(!c){a=g;c=1;k=4}else{c=jd()|0;f[c>>2]=75;c=-1}else k=4;if((k|0)==4){k=-2-a|0;k=c>>>0>k>>>0?k:c;f[l+48>>2]=k;g=l+20|0;f[g>>2]=a;f[l+44>>2]=a;c=a+k|0;a=l+16|0;f[a>>2]=c;f[l+28>>2]=c;c=ob(l,d,e)|0;if(k){l=f[g>>2]|0;b[l+(((l|0)==(f[a>>2]|0))<<31>>31)>>0]=0}}u=m;return c|0}function Gb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,g=0,h=0,i=0,j=0,k=0;k=u;u=u+560|0;j=k+32|0;g=k+16|0;e=k;h=k+48|0;i=k+44|0;if(a&7|0){f[e>>2]=866;f[e+4>>2]=2506;f[e+8>>2]=1210;vc(h,812,e)|0;Ub(h)|0;j=0;u=k;return j|0}if(b>>>0>2147418112){f[g>>2]=866;f[g+4>>2]=2506;f[g+8>>2]=1103;vc(h,812,g)|0;Ub(h)|0;j=0;u=k;return j|0}f[i>>2]=b;a=Nb(a,b,i,d,0)|0;if(c|0)f[c>>2]=f[i>>2];if(a&7|0){f[j>>2]=866;f[j+4>>2]=2558;f[j+8>>2]=1156;vc(h,812,j)|0;Ub(h)|0}j=a;u=k;return j|0}function Hb(a,c,d,e,g){a=a|0;c=c|0;d=d|0;e=e|0;g=g|0;var h=0;do if(!(Sc(a,f[c+8>>2]|0,g)|0)){if(Sc(a,f[c>>2]|0,g)|0){a=c+32|0;if((f[c+16>>2]|0)!=(d|0)?(h=c+20|0,(f[h>>2]|0)!=(d|0)):0){f[a>>2]=e;f[h>>2]=d;e=c+40|0;f[e>>2]=(f[e>>2]|0)+1;if((f[c+36>>2]|0)==1?(f[c+24>>2]|0)==2:0)b[c+54>>0]=1;f[c+44>>2]=4;break}if((e|0)==1)f[a>>2]=1}}else jc(0,c,d,e);while(0);return}function Ib(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,g=0,h=0,i=0;h=a+d|0;c=c&255;if((d|0)>=67){while(a&3){b[a>>0]=c;a=a+1|0}e=h&-4|0;g=e-64|0;i=c|c<<8|c<<16|c<<24;while((a|0)<=(g|0)){f[a>>2]=i;f[a+4>>2]=i;f[a+8>>2]=i;f[a+12>>2]=i;f[a+16>>2]=i;f[a+20>>2]=i;f[a+24>>2]=i;f[a+28>>2]=i;f[a+32>>2]=i;f[a+36>>2]=i;f[a+40>>2]=i;f[a+44>>2]=i;f[a+48>>2]=i;f[a+52>>2]=i;f[a+56>>2]=i;f[a+60>>2]=i;a=a+64|0}while((a|0)<(e|0)){f[a>>2]=i;a=a+4|0}}while((a|0)<(h|0)){b[a>>0]=c;a=a+1|0}return h-d|0}function Jb(a,c,d,e,g){a=a|0;c=c|0;d=d|0;e=e|0;g=g|0;var h=0,i=0,j=0,k=0;b[c+53>>0]=1;do if((f[c+4>>2]|0)==(e|0)){b[c+52>>0]=1;e=c+16|0;h=f[e>>2]|0;j=c+54|0;k=c+48|0;i=c+24|0;a=c+36|0;if(!h){f[e>>2]=d;f[i>>2]=g;f[a>>2]=1;if(!((f[k>>2]|0)==1&(g|0)==1))break;b[j>>0]=1;break}if((h|0)!=(d|0)){f[a>>2]=(f[a>>2]|0)+1;b[j>>0]=1;break}a=f[i>>2]|0;if((a|0)==2){f[i>>2]=g;a=g}if((f[k>>2]|0)==1&(a|0)==1)b[j>>0]=1}while(0);return}function Kb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,g=0,h=0;h=u;u=u+64|0;e=h;if(!(Sc(a,b,0)|0))if((b|0)!=0?(g=pb(b,32,16,0)|0,(g|0)!=0):0){b=e+4|0;d=b+52|0;do{f[b>>2]=0;b=b+4|0}while((b|0)<(d|0));f[e>>2]=g;f[e+8>>2]=a;f[e+12>>2]=-1;f[e+48>>2]=1;La[f[(f[g>>2]|0)+28>>2]&3](g,e,f[c>>2]|0,1);if((f[e+24>>2]|0)==1){f[c>>2]=f[e+16>>2];b=1}else b=0}else b=0;else b=1;u=h;return b|0}function Lb(a,c){a=a|0;c=c|0;var d=0,e=0,g=0,i=0,j=0,k=0,l=0;l=u;u=u+16|0;j=l;k=c&255;b[j>>0]=k;e=a+16|0;g=f[e>>2]|0;if(!g)if(!(Zb(a)|0)){g=f[e>>2]|0;i=4}else d=-1;else i=4;do if((i|0)==4){i=a+20|0;e=f[i>>2]|0;if(e>>>0 >>0?(d=c&255,(d|0)!=(b[a+75>>0]|0)):0){f[i>>2]=e+1;b[e>>0]=k;break}if((Ea[f[a+36>>2]&7](a,j,1)|0)==1)d=h[j>>0]|0;else d=-1}while(0);u=l;return d|0}function Mb(a,c){a=a|0;c=c|0;var d=0,e=0,g=0,h=0,i=0,j=0,k=0;j=a&255;d=a&255;if((f[c+76>>2]|0)>=0?(td(c)|0)!=0:0){if((d|0)!=(b[c+75>>0]|0)?(h=c+20|0,i=f[h>>2]|0,i>>>0<(f[c+16>>2]|0)>>>0):0){f[h>>2]=i+1;b[i>>0]=j}else d=Lb(c,a)|0;sd(c)}else k=3;do if((k|0)==3){if((d|0)!=(b[c+75>>0]|0)?(e=c+20|0,g=f[e>>2]|0,g>>>0<(f[c+16>>2]|0)>>>0):0){f[e>>2]=g+1;b[g>>0]=j;break}d=Lb(c,a)|0}while(0);return d|0}function Nb(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;do if(!a){b=Ma(b)|0;if(c){if(!b)a=0;else a=uc(b)|0;f[c>>2]=a}}else{if(!b){Ta(a);if(!c){b=0;break}f[c>>2]=0;b=0;break}if(d){b=Sb(a,b)|0;a=(b|0)==0?a:b}else b=0;if(c){e=uc(a)|0;f[c>>2]=e}}while(0);return b|0}function Ob(a){a=a|0;var c=0,d=0,e=0;e=a;a:do if(!(e&3))d=4;else{c=e;while(1){if(!(b[a>>0]|0)){a=c;break a}a=a+1|0;c=a;if(!(c&3)){d=4;break}}}while(0);if((d|0)==4){while(1){c=f[a>>2]|0;if(!((c&-2139062144^-2139062144)&c+-16843009))a=a+4|0;else break}if((c&255)<<24>>24)do a=a+1|0;while((b[a>>0]|0)!=0)}return a-e|0}function Pb(a,b){a=+a;b=b|0;var c=0,d=0,e=0;p[s>>3]=a;c=f[s>>2]|0;d=f[s+4>>2]|0;e=zc(c|0,d|0,52)|0;switch(e&2047){case 0:{if(a!=0.0){a=+Pb(a*18446744073709551616.0,b);c=(f[b>>2]|0)+-64|0}else c=0;f[b>>2]=c;break}case 2047:break;default:{f[b>>2]=(e&2047)+-1022;f[s>>2]=c;f[s+4>>2]=d&-2146435073|1071644672;a=+p[s>>3]}}return +a}function Qb(a,c){a=a|0;c=c|0;var d=0,e=0;e=0;while(1){if((h[2140+e>>0]|0)==(a|0)){a=2;break}d=e+1|0;if((d|0)==87){d=2228;e=87;a=5;break}else e=d}if((a|0)==2)if(!e)d=2228;else{d=2228;a=5}if((a|0)==5)while(1){do{a=d;d=d+1|0}while((b[a>>0]|0)!=0);e=e+-1|0;if(!e)break;else a=5}return ed(d,f[c+20>>2]|0)|0}function Rb(a,c,d){a=a|0;c=c|0;d=d|0;var e=0;if(c>>>0>0|(c|0)==0&a>>>0>4294967295){while(1){e=mc(a|0,c|0,10,0)|0;d=d+-1|0;b[d>>0]=e&255|48;e=a;a=Uc(a|0,c|0,10,0)|0;if(!(c>>>0>9|(c|0)==9&e>>>0>4294967295))break;else c=I}c=a}else c=a;if(c)while(1){d=d+-1|0;b[d>>0]=(c>>>0)%10|0|48;if(c>>>0<10)break;else c=(c>>>0)/10|0}return d|0}function Sb(a,b){a=a|0;b=b|0;var c=0,d=0;if(!a){b=Ma(b)|0;return b|0}if(b>>>0>4294967231){b=jd()|0;f[b>>2]=12;b=0;return b|0}c=_a(a+-8|0,b>>>0<11?16:b+11&-8)|0;if(c|0){b=c+8|0;return b|0}c=Ma(b)|0;if(!c){b=0;return b|0}d=f[a+-4>>2]|0;d=(d&-8)-((d&3|0)==0?8:4)|0;kb(c|0,a|0,(d>>>0>>0?d:b)|0)|0;Ta(a);b=c;return b|0}function Tb(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;var g=0,h=0,i=0;a=c+16|0;g=f[a>>2]|0;h=c+36|0;i=c+24|0;do if(g){if((g|0)!=(d|0)){f[h>>2]=(f[h>>2]|0)+1;f[i>>2]=2;b[c+54>>0]=1;break}if((f[i>>2]|0)==2)f[i>>2]=e}else{f[a>>2]=d;f[i>>2]=e;f[h>>2]=1}while(0);return}function Ub(a){a=a|0;var c=0,d=0,e=0,g=0;e=f[119]|0;if((f[e+76>>2]|0)>-1)g=td(e)|0;else g=0;do if((Mc(a,e)|0)<0)a=1;else{if((b[e+75>>0]|0)!=10?(c=e+20|0,d=f[c>>2]|0,d>>>0<(f[e+16>>2]|0)>>>0):0){f[c>>2]=d+1;b[d>>0]=10;a=0;break}a=(Lb(e,10)|0)<0}while(0);if(g|0)sd(e);return a<<31>>31|0}function Vb(a,b,c,d,e,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;g=g|0;if(Sc(a,f[b+8>>2]|0,g)|0)Jb(0,b,c,d,e);else{a=f[a+8>>2]|0;Ka[f[(f[a>>2]|0)+20>>2]&3](a,b,c,d,e,g)}return}function Wb(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;var f=0,g=0;g=u;u=u+256|0;f=g;if((c|0)>(d|0)&(e&73728|0)==0){e=c-d|0;Ib(f|0,b|0,(e>>>0<256?e:256)|0)|0;if(e>>>0>255){b=c-d|0;do{Nc(a,f,256);e=e+-256|0}while(e>>>0>255);e=b&255}Nc(a,f,e)}u=g;return}function Xb(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;if(Sc(a,f[b+8>>2]|0,0)|0)Tb(0,b,c,d);else{a=f[a+8>>2]|0;La[f[(f[a>>2]|0)+28>>2]&3](a,b,c,d)}return}function Yb(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0,g=0;e=u;u=u+32|0;g=e;d=e+20|0;f[g>>2]=f[a+60>>2];f[g+4>>2]=0;f[g+8>>2]=b;f[g+12>>2]=d;f[g+16>>2]=c;if((Ic(xa(140,g|0)|0)|0)<0){f[d>>2]=-1;a=-1}else a=f[d>>2]|0;u=e;return a|0}function Zb(a){a=a|0;var c=0,d=0;c=a+74|0;d=b[c>>0]|0;b[c>>0]=d+255|d;c=f[a>>2]|0;if(!(c&8)){f[a+8>>2]=0;f[a+4>>2]=0;d=f[a+44>>2]|0;f[a+28>>2]=d;f[a+20>>2]=d;f[a+16>>2]=d+(f[a+48>>2]|0);a=0}else{f[a>>2]=c|32;a=-1}return a|0}function _b(a,c){a=a|0;c=c|0;var d=0,e=0;d=b[a>>0]|0;e=b[c>>0]|0;if(d<<24>>24==0?1:d<<24>>24!=e<<24>>24)a=e;else{do{a=a+1|0;c=c+1|0;d=b[a>>0]|0;e=b[c>>0]|0}while(!(d<<24>>24==0?1:d<<24>>24!=e<<24>>24));a=e}return (d&255)-(a&255)|0}function $b(a,c,d){a=a|0;c=c|0;d=d|0;var e=0,g=0;g=u;u=u+32|0;e=g;f[a+36>>2]=1;if((f[a>>2]&64|0)==0?(f[e>>2]=f[a+60>>2],f[e+4>>2]=21523,f[e+8>>2]=g+16,na(54,e|0)|0):0)b[a+75>>0]=-1;e=mb(a,c,d)|0;u=g;return e|0}function ac(a){a=a|0;var b=0,c=0;c=a+15&-16|0;b=f[r>>2]|0;a=b+c|0;if((c|0)>0&(a|0)<(b|0)|(a|0)<0){da()|0;ra(12);return -1}f[r>>2]=a;if((a|0)>(ca()|0)?(ba()|0)==0:0){f[r>>2]=b;ra(12);return -1}return b|0}function bc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,g=0;e=X(c,b)|0;c=(b|0)==0?0:c;if((f[d+76>>2]|0)>-1){g=(td(d)|0)==0;a=zb(a,e,d)|0;if(!g)sd(d)}else a=zb(a,e,d)|0;if((a|0)!=(e|0))c=(a>>>0)/(b>>>0)|0;return c|0}function cc(a,b,c,d,e,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;g=g|0;if(Sc(a,f[b+8>>2]|0,g)|0)Jb(0,b,c,d,e);return}function dc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;if(Sc(a,f[b+8>>2]|0,0)|0)Tb(0,b,c,d);return}function ec(a){a=a|0;var c=0,d=0,e=0;d=f[a>>2]|0;e=(b[d>>0]|0)+-48|0;if(e>>>0<10){c=0;do{c=e+(c*10|0)|0;d=d+1|0;f[a>>2]=d;e=(b[d>>0]|0)+-48|0}while(e>>>0<10)}else c=0;return c|0}function fc(){var a=0,b=0;a=rc()|0;if((a|0?(b=f[a>>2]|0,b|0):0)?(a=b+48|0,(f[a>>2]&-256|0)==1126902528?(f[a+4>>2]|0)==1129074247:0):0)Jc(f[b+12>>2]|0);Jc($c()|0)}function gc(a,c,d,e){a=a|0;c=c|0;d=d|0;e=e|0;if(!((a|0)==0&(c|0)==0))do{d=d+-1|0;b[d>>0]=h[2122+(a&15)>>0]|0|e;a=zc(a|0,c|0,4)|0;c=I}while(!((a|0)==0&(c|0)==0));return d|0}function hc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;e=u;u=u+16|0;d=e;f[d>>2]=f[c>>2];a=Ea[f[(f[a>>2]|0)+16>>2]&7](a,b,d)|0;if(a)f[c>>2]=f[d>>2];u=e;return a&1|0}function ic(a){a=a|0;var c=0;c=b[w+(a&255)>>0]|0;if((c|0)<8)return c|0;c=b[w+(a>>8&255)>>0]|0;if((c|0)<8)return c+8|0;c=b[w+(a>>16&255)>>0]|0;if((c|0)<8)return c+16|0;return (b[w+(a>>>24)>>0]|0)+24|0}function jc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0;if((f[b+4>>2]|0)==(c|0)?(e=b+28|0,(f[e>>2]|0)!=1):0)f[e>>2]=d;return}function kc(a,c,d){a=a|0;c=c|0;d=d|0;if(!((a|0)==0&(c|0)==0))do{d=d+-1|0;b[d>>0]=a&7|48;a=zc(a|0,c|0,3)|0;c=I}while(!((a|0)==0&(c|0)==0));return d|0}function lc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=a+20|0;e=f[d>>2]|0;a=(f[a+16>>2]|0)-e|0;a=a>>>0>c>>>0?c:a;kb(e|0,b|0,a|0)|0;f[d>>2]=(f[d>>2]|0)+a;return c|0}function mc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;var e=0,g=0;g=u;u=u+16|0;e=g|0;Za(a,b,c,d,e)|0;u=g;return (I=f[e+4>>2]|0,f[e>>2]|0)|0}function nc(a,b){a=a|0;b=b|0;var c=0,d=0;d=u;u=u+48|0;c=d;f[c>>2]=40;tb(a,b,c)|0;u=d;return f[c+32>>2]|0}function oc(a,b){a=a|0;b=b|0;var c=0,d=0;d=u;u=u+48|0;c=d;f[c>>2]=40;tb(a,b,c)|0;u=d;return f[c+12>>2]|0}function pc(a,b){a=a|0;b=b|0;var c=0,d=0;d=u;u=u+48|0;c=d;f[c>>2]=40;tb(a,b,c)|0;u=d;return f[c+8>>2]|0}function qc(a,b){a=a|0;b=b|0;var c=0,d=0;d=u;u=u+48|0;c=d;f[c>>2]=40;tb(a,b,c)|0;u=d;return f[c+4>>2]|0}function rc(){var a=0,b=0;a=u;u=u+16|0;if(!(ua(5136,2)|0)){b=ma(f[1285]|0)|0;u=a;return b|0}else Ac(4307,a);return 0}function sc(a){a=a|0;var b=0,c=0;b=u;u=u+16|0;c=b;a=pd(f[a+60>>2]|0)|0;f[c>>2]=a;a=Ic(qa(6,c|0)|0)|0;u=b;return a|0}function tc(a){a=a|0;var b=0;b=u;u=u+16|0;Ta(a);if(!(oa(f[1285]|0,0)|0)){u=b;return}else Ac(4406,b)}function uc(a){a=a|0;var b=0;if(!a)return 0;else{b=f[a+-4>>2]|0;a=b&3;return ((a|0)==1?0:(b&-8)-((a|0)==0?8:4)|0)|0}return 0}function vc(a,b,c){a=a|0;b=b|0;c=c|0;var d=0,e=0;d=u;u=u+16|0;e=d;f[e>>2]=c;c=Yc(a,b,e)|0;u=d;return c|0}function wc(a,b,c,d,e,f,g){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;g=g|0;Ka[a&3](b|0,c|0,d|0,e|0,f|0,g|0)}function xc(){var a=0;a=u;u=u+16|0;if(!(wa(5140,6)|0)){u=a;return}else Ac(4356,a)}function yc(a,b,c){a=a|0;b=b|0;c=c|0;if((c|0)<32){I=b< >>32-c;return a< >>c;return a>>>c|(b&(1< >>c-32|0}function Ac(a,b){a=a|0;b=b|0;var c=0;c=u;u=u+16|0;f[c>>2]=b;b=f[26]|0;ob(b,a,c)|0;Mb(10,b)|0;sa()}function Bc(){}function Cc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;d=b-d-(c>>>0>a>>>0|0)>>>0;return (I=d,a-c>>>0|0)|0}function Dc(a,b){a=a|0;b=b|0;if(!b)b=0;else b=rb(f[b>>2]|0,f[b+4>>2]|0,a)|0;return (b|0?b:a)|0}function Ec(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;Fa[a&3](b|0,c|0,d|0,e|0,f|0)}function Fc(a){a=+a;var b=0;p[s>>3]=a;b=f[s>>2]|0;I=f[s+4>>2]|0;return b|0}function Gc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;c=a+c>>>0;return (I=b+d+(c>>>0>>0|0)>>>0,c|0)|0}function Hc(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;La[a&3](b|0,c|0,d|0,e|0)}function Ic(a){a=a|0;var b=0;if(a>>>0>4294963200){b=jd()|0;f[b>>2]=0-a;a=-1}return a|0}function Jc(a){a=a|0;var b=0;b=u;u=u+16|0;Ja[a&3]();Ac(4459,b)}function Kc(a){a=a|0;if(!a)a=0;else a=(pb(a,32,88,0)|0)!=0;return a&1|0}function Lc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return Ea[a&7](b|0,c|0,d|0)|0}function Mc(a,b){a=a|0;b=b|0;var c=0;c=Ob(a)|0;return ((bc(a,1,c,b)|0)!=(c|0))<<31>>31|0}function Nc(a,b,c){a=a|0;b=b|0;c=c|0;if(!(f[a>>2]&32))zb(b,c,a)|0;return}function Oc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;Ia[a&0](b|0,c|0,d|0)}function Pc(a){a=a|0;var b=0;b=u;u=u+a|0;u=u+15&-16;return b|0}function Qc(a){a=a|0;var b=0;b=(ld()|0)+188|0;return Qb(a,f[b>>2]|0)|0}function Rc(a,b){a=a|0;b=b|0;if(!a)a=0;else a=Ab(a,b,0)|0;return a|0}function Sc(a,b,c){a=a|0;b=b|0;c=c|0;return (a|0)==(b|0)|0}function Tc(a,b){a=a|0;b=b|0;var c=0;c=Vc(a|0)|0;return ((b|0)==0?a:c)|0}function Uc(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;return Za(a,b,c,d,0)|0}function Vc(a){a=a|0;return (a&255)<<24|(a>>8&255)<<16|(a>>16&255)<<8|a>>>24|0}function Wc(a,b,c,d,e,f){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;f=f|0;$(6)}function Xc(a,b){a=a|0;b=b|0;if(!x){x=a;y=b}}function Yc(a,b,c){a=a|0;b=b|0;c=c|0;return Fb(a,2147483647,b,c)|0}function Zc(a,b,c,d,e){a=a|0;b=b|0;c=c|0;d=d|0;e=e|0;$(1)}function _c(a){a=a|0;sd(a);nd(a);return}function $c(){var a=0;a=f[182]|0;f[182]=a+0;return a|0}function ad(a){a=a|0;ta(a|0)|0;fc()}function bd(a,b){a=a|0;b=b|0;return Ha[a&1](b|0)|0}function cd(a,b){a=a|0;b=b|0;u=a;v=b}function dd(a,b,c,d){a=a|0;b=b|0;c=c|0;d=d|0;$(7)}function ed(a,b){a=a|0;b=b|0;return Dc(a,b)|0}function fd(a,b){a=a|0;b=b|0;Ga[a&7](b|0)}function gd(a,b,c){a=a|0;b=b|0;c=c|0;$(0);return 0}function hd(a,b){a=+a;b=b|0;return +(+Pb(a,b))}function id(a,b,c){a=a|0;b=b|0;c=c|0;$(4)}function jd(){return (ld()|0)+64|0}function kd(a){a=a|0;Ja[a&3]()}function ld(){return xd()|0}function md(a){a=a|0;u=a}function nd(a){a=a|0;Ta(a);return}function od(a){a=a|0;I=a}function pd(a){a=a|0;return a|0}function qd(){return 5072}function rd(a){a=a|0;$(3);return 0}function sd(a){a=a|0;return}function td(a){a=a|0;return 0}function ud(){return I|0}function vd(){return u|0}function wd(a){a=a|0;$(2)}function xd(){return 232}function yd(){$(5)} - -// EMSCRIPTEN_END_FUNCS -var Ea=[gd,mb,Yb,$b,lc,Kb,gd,gd];var Fa=[Zc,Hb,nb,Zc];var Ga=[wd,sd,_c,sd,sd,_c,tc,wd];var Ha=[rd,sc];var Ia=[id];var Ja=[yd,Bb,xc,yd];var Ka=[Wc,cc,Vb,Wc];var La=[dd,dc,Xb,dd];return{stackSave:vd,_i64Subtract:Cc,_crn_get_bytes_per_block:ib,setThrew:Xc,dynCall_viii:Oc,_bitshift64Lshr:zc,_bitshift64Shl:yc,dynCall_viiii:Hc,setTempRet0:od,_crn_decompress:$a,_memset:Ib,_sbrk:ac,_memcpy:kb,stackAlloc:Pc,_crn_get_height:pc,dynCall_vi:fd,getTempRet0:ud,_crn_get_levels:oc,_crn_get_uncompressed_size:hb,_i64Add:Gc,dynCall_iiii:Lc,_emscripten_get_global_libc:qd,dynCall_ii:bd,___udivdi3:Uc,_llvm_bswap_i32:Vc,dynCall_viiiii:Ec,___cxa_can_catch:hc,_free:Ta,runPostSets:Bc,dynCall_viiiiii:wc,establishStackSpace:cd,___uremdi3:mc,___cxa_is_pointer_type:Kc,stackRestore:md,_malloc:Ma,_emscripten_replace_memory:Da,dynCall_v:kd,_crn_get_width:qc,_crn_get_dxt_format:nc}}) - - -// EMSCRIPTEN_END_ASM -(Module.asmGlobalArg,Module.asmLibraryArg,buffer);var stackSave=Module["stackSave"]=asm["stackSave"];var getTempRet0=Module["getTempRet0"]=asm["getTempRet0"];var _memset=Module["_memset"]=asm["_memset"];var setThrew=Module["setThrew"]=asm["setThrew"];var _bitshift64Lshr=Module["_bitshift64Lshr"]=asm["_bitshift64Lshr"];var _bitshift64Shl=Module["_bitshift64Shl"]=asm["_bitshift64Shl"];var setTempRet0=Module["setTempRet0"]=asm["setTempRet0"];var _crn_decompress=Module["_crn_decompress"]=asm["_crn_decompress"];var _crn_get_bytes_per_block=Module["_crn_get_bytes_per_block"]=asm["_crn_get_bytes_per_block"];var _sbrk=Module["_sbrk"]=asm["_sbrk"];var _memcpy=Module["_memcpy"]=asm["_memcpy"];var stackAlloc=Module["stackAlloc"]=asm["stackAlloc"];var _crn_get_height=Module["_crn_get_height"]=asm["_crn_get_height"];var _i64Subtract=Module["_i64Subtract"]=asm["_i64Subtract"];var _crn_get_levels=Module["_crn_get_levels"]=asm["_crn_get_levels"];var _crn_get_uncompressed_size=Module["_crn_get_uncompressed_size"]=asm["_crn_get_uncompressed_size"];var _i64Add=Module["_i64Add"]=asm["_i64Add"];var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=asm["_emscripten_get_global_libc"];var ___udivdi3=Module["___udivdi3"]=asm["___udivdi3"];var _llvm_bswap_i32=Module["_llvm_bswap_i32"]=asm["_llvm_bswap_i32"];var ___cxa_can_catch=Module["___cxa_can_catch"]=asm["___cxa_can_catch"];var _free=Module["_free"]=asm["_free"];var runPostSets=Module["runPostSets"]=asm["runPostSets"];var establishStackSpace=Module["establishStackSpace"]=asm["establishStackSpace"];var ___uremdi3=Module["___uremdi3"]=asm["___uremdi3"];var ___cxa_is_pointer_type=Module["___cxa_is_pointer_type"]=asm["___cxa_is_pointer_type"];var stackRestore=Module["stackRestore"]=asm["stackRestore"];var _malloc=Module["_malloc"]=asm["_malloc"];var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=asm["_emscripten_replace_memory"];var _crn_get_width=Module["_crn_get_width"]=asm["_crn_get_width"];var _crn_get_dxt_format=Module["_crn_get_dxt_format"]=asm["_crn_get_dxt_format"];var dynCall_iiii=Module["dynCall_iiii"]=asm["dynCall_iiii"];var dynCall_viiiii=Module["dynCall_viiiii"]=asm["dynCall_viiiii"];var dynCall_vi=Module["dynCall_vi"]=asm["dynCall_vi"];var dynCall_ii=Module["dynCall_ii"]=asm["dynCall_ii"];var dynCall_viii=Module["dynCall_viii"]=asm["dynCall_viii"];var dynCall_v=Module["dynCall_v"]=asm["dynCall_v"];var dynCall_viiiiii=Module["dynCall_viiiiii"]=asm["dynCall_viiiiii"];var dynCall_viiii=Module["dynCall_viiii"]=asm["dynCall_viiii"];Runtime.stackAlloc=Module["stackAlloc"];Runtime.stackSave=Module["stackSave"];Runtime.stackRestore=Module["stackRestore"];Runtime.establishStackSpace=Module["establishStackSpace"];Runtime.setTempRet0=Module["setTempRet0"];Runtime.getTempRet0=Module["getTempRet0"];Module["asm"]=asm;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}ExitStatus.prototype=new Error;ExitStatus.prototype.constructor=ExitStatus;var initialStackTop;var preloadStartTime=null;var calledMain=false;dependenciesFulfilled=function runCaller(){if(!Module["calledRun"])run();if(!Module["calledRun"])dependenciesFulfilled=runCaller};Module["callMain"]=Module.callMain=function callMain(args){args=args||[];ensureInitRuntime();var argc=args.length+1;function pad(){for(var i=0;i<4-1;i++){argv.push(0)}}var argv=[allocate(intArrayFromString(Module["thisProgram"]),"i8",ALLOC_NORMAL)];pad();for(var i=0;i 0){return}preRun();if(runDependencies>0)return;if(Module["calledRun"])return;function doRun(){if(Module["calledRun"])return;Module["calledRun"]=true;if(ABORT)return;ensureInitRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(Module["_main"]&&shouldRunNow)Module["callMain"](args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout((function(){setTimeout((function(){Module["setStatus"]("")}),1);doRun()}),1)}else{doRun()}}Module["run"]=Module.run=run;function exit(status,implicit){if(implicit&&Module["noExitRuntime"]){return}if(Module["noExitRuntime"]){}else{ABORT=true;EXITSTATUS=status;STACKTOP=initialStackTop;exitRuntime();if(Module["onExit"])Module["onExit"](status)}if(ENVIRONMENT_IS_NODE){process["exit"](status)}Module["quit"](status,new ExitStatus(status))}Module["exit"]=Module.exit=exit;var abortDecorators=[];function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}if(what!==undefined){Module.print(what);Module.printErr(what);what=JSON.stringify(what)}else{what=""}ABORT=true;EXITSTATUS=1;var extra="\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.";var output="abort("+what+") at "+stackTrace()+extra;if(abortDecorators){abortDecorators.forEach((function(decorator){output=decorator(output,what)}))}throw output}Module["abort"]=Module.abort=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"]){shouldRunNow=false}Module["noExitRuntime"]=true;run() - -export default Module; diff --git a/Source/WorkersES6/transcodeCRNToDXT.js b/Source/WorkersES6/transcodeCRNToDXT.js deleted file mode 100644 index a6b756ffe48e..000000000000 --- a/Source/WorkersES6/transcodeCRNToDXT.js +++ /dev/null @@ -1,140 +0,0 @@ -import CompressedTextureBuffer from "../Core/CompressedTextureBuffer.js"; -import defined from "../Core/defined.js"; -import PixelFormat from "../Core/PixelFormat.js"; -import RuntimeError from "../Core/RuntimeError.js"; -import crunch from "../ThirdParty/crunch.js"; -import createTaskProcessorWorker from "./createTaskProcessorWorker.js"; - -// Modified from texture-tester -// See: -// https://github.com/toji/texture-tester/blob/master/js/webgl-texture-util.js -// http://toji.github.io/texture-tester/ - -/** - * @license - * - * Copyright (c) 2014, Brandon Jones. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// Taken from crnlib.h -var CRN_FORMAT = { - cCRNFmtInvalid: -1, - - cCRNFmtDXT1: 0, - // cCRNFmtDXT3 is not currently supported when writing to CRN - only DDS. - cCRNFmtDXT3: 1, - cCRNFmtDXT5: 2, - - // Crunch supports more formats than this, but we can't use them here. -}; - -// Mapping of Crunch formats to DXT formats. -var DXT_FORMAT_MAP = {}; -DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT1] = PixelFormat.RGB_DXT1; -DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT3] = PixelFormat.RGBA_DXT3; -DXT_FORMAT_MAP[CRN_FORMAT.cCRNFmtDXT5] = PixelFormat.RGBA_DXT5; - -var dst; -var dxtData; -var cachedDstSize = 0; - -// Copy an array of bytes into or out of the emscripten heap. -function arrayBufferCopy(src, dst, dstByteOffset, numBytes) { - var i; - var dst32Offset = dstByteOffset / 4; - var tail = numBytes % 4; - var src32 = new Uint32Array(src.buffer, 0, (numBytes - tail) / 4); - var dst32 = new Uint32Array(dst.buffer); - for (i = 0; i < src32.length; i++) { - dst32[dst32Offset + i] = src32[i]; - } - for (i = numBytes - tail; i < numBytes; i++) { - dst[dstByteOffset + i] = src[i]; - } -} - -/** - * @private - */ -function transcodeCRNToDXT(arrayBuffer, transferableObjects) { - // Copy the contents of the arrayBuffer into emscriptens heap. - var srcSize = arrayBuffer.byteLength; - var bytes = new Uint8Array(arrayBuffer); - var src = crunch._malloc(srcSize); - arrayBufferCopy(bytes, crunch.HEAPU8, src, srcSize); - - // Determine what type of compressed data the file contains. - var crnFormat = crunch._crn_get_dxt_format(src, srcSize); - var format = DXT_FORMAT_MAP[crnFormat]; - if (!defined(format)) { - throw new RuntimeError("Unsupported compressed format."); - } - - // Gather basic metrics about the DXT data. - var levels = crunch._crn_get_levels(src, srcSize); - var width = crunch._crn_get_width(src, srcSize); - var height = crunch._crn_get_height(src, srcSize); - - // Determine the size of the decoded DXT data. - var dstSize = 0; - var i; - for (i = 0; i < levels; ++i) { - dstSize += PixelFormat.compressedTextureSizeInBytes( - format, - width >> i, - height >> i - ); - } - - // Allocate enough space on the emscripten heap to hold the decoded DXT data - // or reuse the existing allocation if a previous call to this function has - // already acquired a large enough buffer. - if (cachedDstSize < dstSize) { - if (defined(dst)) { - crunch._free(dst); - } - dst = crunch._malloc(dstSize); - dxtData = new Uint8Array(crunch.HEAPU8.buffer, dst, dstSize); - cachedDstSize = dstSize; - } - - // Decompress the DXT data from the Crunch file into the allocated space. - crunch._crn_decompress(src, srcSize, dst, dstSize, 0, levels); - - // Release the crunch file data from the emscripten heap. - crunch._free(src); - - // Mipmaps are unsupported, so copy the level 0 texture - // When mipmaps are supported, a copy will still be necessary as dxtData is a view on the heap. - var length = PixelFormat.compressedTextureSizeInBytes(format, width, height); - - // Get a copy of the 0th mip level. dxtData will exceed length when there are more mip levels. - // Equivalent to dxtData.slice(0, length), which is not supported in IE11 - var level0DXTDataView = dxtData.subarray(0, length); - var level0DXTData = new Uint8Array(length); - level0DXTData.set(level0DXTDataView, 0); - - transferableObjects.push(level0DXTData.buffer); - return new CompressedTextureBuffer(format, width, height, level0DXTData); -} -export default createTaskProcessorWorker(transcodeCRNToDXT); diff --git a/Source/WorkersES6/transcodeKTX2.js b/Source/WorkersES6/transcodeKTX2.js new file mode 100644 index 000000000000..19ea502f1065 --- /dev/null +++ b/Source/WorkersES6/transcodeKTX2.js @@ -0,0 +1,52 @@ +/* global require */ +import defined from "../Core/defined.js"; +import parseKTX2 from "../Core/parseKTX2.js"; + +import createTaskProcessorWorker from "./createTaskProcessorWorker.js"; + +var transcoderModule; + +function transcode(parameters, transferableObjects) { + var ktx2Buffer = parameters.ktx2Buffer; + var supportedTargetFormats = parameters.supportedTargetFormats; + return parseKTX2( + ktx2Buffer, + supportedTargetFormats, + transcoderModule, + transferableObjects + ); +} + +function initWorker(compiledModule) { + transcoderModule = compiledModule; + transcoderModule.initializeBasis(); + + self.onmessage = createTaskProcessorWorker(transcode); + self.postMessage(true); +} + +function transcodeKTX2(event) { + var data = event.data; + + // Expect the first message to be to load a web assembly module + var wasmConfig = data.webAssemblyConfig; + if (defined(wasmConfig)) { + // Require and compile WebAssembly module, or use fallback if not supported + return require([wasmConfig.modulePath], function (mscBasisTranscoder) { + if (defined(wasmConfig.wasmBinaryFile)) { + if (!defined(mscBasisTranscoder)) { + mscBasisTranscoder = self.MSC_TRANSCODER; + } + + mscBasisTranscoder(wasmConfig).then(function (compiledModule) { + initWorker(compiledModule); + }); + } else { + return mscBasisTranscoder().then(function (transcoder) { + initWorker(transcoder); + }); + } + }); + } +} +export default transcodeKTX2; diff --git a/Specs/Core/loadCRNSpec.js b/Specs/Core/loadCRNSpec.js deleted file mode 100644 index f06ff27dfe94..000000000000 --- a/Specs/Core/loadCRNSpec.js +++ /dev/null @@ -1,538 +0,0 @@ -import { loadCRN } from "../../Source/Cesium.js"; -import { PixelFormat } from "../../Source/Cesium.js"; -import { Request } from "../../Source/Cesium.js"; -import { RequestErrorEvent } from "../../Source/Cesium.js"; -import { RequestScheduler } from "../../Source/Cesium.js"; -import { Resource } from "../../Source/Cesium.js"; - -describe("Core/loadCRN", function () { - var validCompressed = new Uint8Array([ - 72, - 120, - 0, - 74, - 227, - 123, - 0, - 0, - 0, - 138, - 92, - 167, - 0, - 4, - 0, - 4, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 74, - 0, - 0, - 22, - 0, - 1, - 0, - 0, - 96, - 0, - 0, - 12, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29, - 0, - 0, - 108, - 0, - 0, - 0, - 137, - 0, - 10, - 96, - 0, - 0, - 0, - 0, - 0, - 0, - 16, - 4, - 9, - 130, - 0, - 0, - 0, - 0, - 0, - 0, - 109, - 4, - 0, - 0, - 198, - 96, - 128, - 0, - 0, - 0, - 0, - 0, - 26, - 80, - 0, - 0, - 6, - 96, - 0, - 0, - 0, - 0, - 0, - 0, - 16, - 0, - 51, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 128, - 1, - 152, - 0, - 0, - 0, - 0, - 0, - 0, - 4, - 0, - ]); - var validCompressedMipmap = new Uint8Array([ - 72, - 120, - 0, - 82, - 183, - 141, - 0, - 0, - 0, - 148, - 151, - 24, - 0, - 4, - 0, - 4, - 3, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 82, - 0, - 0, - 22, - 0, - 1, - 0, - 0, - 104, - 0, - 0, - 12, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29, - 0, - 0, - 116, - 0, - 0, - 0, - 145, - 0, - 0, - 0, - 146, - 0, - 0, - 0, - 147, - 0, - 130, - 97, - 0, - 0, - 0, - 0, - 0, - 4, - 35, - 37, - 0, - 3, - 48, - 0, - 0, - 0, - 0, - 0, - 0, - 8, - 200, - 0, - 198, - 96, - 128, - 0, - 0, - 0, - 0, - 0, - 26, - 80, - 0, - 0, - 6, - 96, - 0, - 0, - 0, - 0, - 0, - 0, - 16, - 0, - 51, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 128, - 1, - 152, - 0, - 0, - 0, - 0, - 0, - 0, - 4, - 0, - 0, - 0, - ]); - var fakeXHR; - - beforeEach(function () { - fakeXHR = jasmine.createSpyObj("XMLHttpRequest", [ - "send", - "open", - "setRequestHeader", - "abort", - "getAllResponseHeaders", - ]); - fakeXHR.simulateLoad = function (response) { - fakeXHR.simulateHttpResponse(200, response); - }; - fakeXHR.simulateError = function () { - fakeXHR.response = ""; - if (typeof fakeXHR.onerror === "function") { - fakeXHR.onerror(); - } - }; - fakeXHR.simulateHttpResponse = function (statusCode, response) { - fakeXHR.status = statusCode; - fakeXHR.response = response; - if (typeof fakeXHR.onload === "function") { - fakeXHR.onload(); - } - }; - - spyOn(window, "XMLHttpRequest").and.returnValue(fakeXHR); - }); - - it("throws with no url", function () { - expect(function () { - loadCRN(); - }).toThrowDeveloperError(); - }); - - it("creates and sends request without any custom headers", function () { - var testUrl = "http://example.invalid/testuri"; - loadCRN(testUrl); - - expect(fakeXHR.open).toHaveBeenCalledWith("GET", testUrl, true); - expect(fakeXHR.setRequestHeader).not.toHaveBeenCalled(); - expect(fakeXHR.send).toHaveBeenCalled(); - }); - - it("creates and sends request with custom headers with Resource", function () { - var testUrl = "http://example.invalid/testuri"; - var resource = new Resource({ - url: testUrl, - headers: { - Accept: "application/json", - "Cache-Control": "no-cache", - }, - }); - - loadCRN(resource); - - expect(fakeXHR.open).toHaveBeenCalledWith("GET", testUrl, true); - expect(fakeXHR.setRequestHeader.calls.count()).toEqual(2); - expect(fakeXHR.setRequestHeader).toHaveBeenCalledWith( - "Accept", - "application/json" - ); - expect(fakeXHR.setRequestHeader).toHaveBeenCalledWith( - "Cache-Control", - "no-cache" - ); - expect(fakeXHR.send).toHaveBeenCalled(); - }); - - it("returns a promise that rejects when the request errors", function () { - var testUrl = "http://example.invalid/testuri"; - var promise = loadCRN(testUrl); - - expect(promise).toBeDefined(); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - - fakeXHR.simulateError(); - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeInstanceOf(RequestErrorEvent); - expect(rejectedError.statusCode).toBeUndefined(); - expect(rejectedError.response).toBeUndefined(); - }); - - it("returns a promise that rejects when the request results in an HTTP error code", function () { - var testUrl = "http://example.invalid/testuri"; - var promise = loadCRN(testUrl); - - expect(promise).toBeDefined(); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - - var error = "some error"; - fakeXHR.simulateHttpResponse(404, error); - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeInstanceOf(RequestErrorEvent); - expect(rejectedError.statusCode).toEqual(404); - expect(rejectedError.response).toEqual(error); - }); - - it("returns a promise that resolves with undefined when statusCode is 204", function () { - var testUrl = "http://example.invalid/testuri"; - var promise = loadCRN(testUrl); - - expect(promise).toBeDefined(); - - var resolved = false; - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolved = true; - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - - fakeXHR.simulateHttpResponse(204); - expect(resolved).toBe(true); - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - }); - - it("returns a promise that resolves to a compressed texture when the request loads", function () { - var testUrl = "http://example.invalid/testuri"; - var promise = loadCRN(testUrl); - - expect(promise).toBeDefined(); - - var resolvedValue; - var rejectedError; - var newPromise = promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - - var response = validCompressed.buffer; - fakeXHR.simulateLoad(response); - - return newPromise.then(function () { - expect(resolvedValue).toBeDefined(); - expect(resolvedValue.width).toEqual(4); - expect(resolvedValue.height).toEqual(4); - expect( - PixelFormat.isCompressedFormat(resolvedValue.internalFormat) - ).toEqual(true); - expect(resolvedValue.bufferView).toBeDefined(); - expect(rejectedError).toBeUndefined(); - }); - }); - - it("returns a promise that resolves to a compressed texture containing the first mip level of the original texture", function () { - var testUrl = "http://example.invalid/testuri"; - var promise = loadCRN(testUrl); - - expect(promise).toBeDefined(); - - var resolvedValue; - var rejectedError; - var newPromise = promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - - var response = validCompressedMipmap.buffer; - fakeXHR.simulateLoad(response); - - return newPromise.then(function () { - expect(resolvedValue).toBeDefined(); - expect(resolvedValue.width).toEqual(4); - expect(resolvedValue.height).toEqual(4); - expect( - PixelFormat.isCompressedFormat(resolvedValue.internalFormat) - ).toEqual(true); - expect(resolvedValue.bufferView).toBeDefined(); - expect(rejectedError).toBeUndefined(); - }); - }); - - it("returns undefined if the request is throttled", function () { - var oldMaximumRequests = RequestScheduler.maximumRequests; - RequestScheduler.maximumRequests = 0; - - var promise = loadCRN( - new Resource({ - url: "http://example.invalid/testuri", - request: new Request({ - throttle: true, - }), - }) - ); - expect(promise).toBeUndefined(); - - RequestScheduler.maximumRequests = oldMaximumRequests; - }); -}); diff --git a/Specs/Core/loadKTX2Spec.js b/Specs/Core/loadKTX2Spec.js new file mode 100644 index 000000000000..a69102774534 --- /dev/null +++ b/Specs/Core/loadKTX2Spec.js @@ -0,0 +1,295 @@ +import { loadKTX2 } from "../../Source/Cesium.js"; +import { KTX2Transcoder } from "../../Source/Cesium.js"; +import { PixelFormat } from "../../Source/Cesium.js"; +import { Resource } from "../../Source/Cesium.js"; +import { RuntimeError } from "../../Source/Cesium.js"; + +describe("Core/loadKTX2", function () { + it("throws with no url", function () { + expect(function () { + loadKTX2(); + }).toThrowDeveloperError(); + }); + + it("throws with unknown supported formats", function () { + expect(function () { + KTX2Transcoder.transcode(new Uint8Array()); + }).toThrowDeveloperError(); + }); + + it("throws if loadKTX2 is called with invalid url", function () { + var testUrl = "http://example.invalid/testuri"; + var promise = loadKTX2(testUrl); + return promise + .then(function (value) { + fail(); + }) + .otherwise(function (error) { + expect(error).toBeDefined(); + }); + }); + + function expectKTX2TranscodeResult( + url, + supportedFormats, + width, + height, + isCompressed + ) { + var resource = Resource.createIfNeeded(url); + var loadPromise = resource.fetchArrayBuffer(); + return loadPromise.then(function (buffer) { + var promise = KTX2Transcoder.transcode(buffer, supportedFormats); + return promise.then(function (result) { + expect(result).toBeDefined(); + expect(result.width).toEqual(width); + expect(result.height).toEqual(height); + expect(PixelFormat.isCompressedFormat(result.internalFormat)).toEqual( + isCompressed + ); + expect(result.bufferView).toBeDefined(); + }); + }); + } + + it("transcodes ETC1S ktx2 to etc", function () { + return expectKTX2TranscodeResult( + "./Data/Images/Green4x4_ETC1S.ktx2", + { etc: true }, + 4, + 4, + true + ); + }); + + it("transcodes UASTC ktx2 to etc", function () { + return expectKTX2TranscodeResult( + "./Data/Images/Logo32x32_UASTC_Zstd.ktx2", + { etc: true }, + 32, + 32, + true + ); + }); + + it("transcodes ETC1S ktx2 to etc1", function () { + return expectKTX2TranscodeResult( + "./Data/Images/Green4x4_ETC1S.ktx2", + { etc1: true }, + 4, + 4, + true + ); + }); + + it("transcodes UASTC ktx2 to etc1", function () { + return expectKTX2TranscodeResult( + "./Data/Images/Logo32x32_UASTC_Zstd.ktx2", + { etc1: true }, + 32, + 32, + true + ); + }); + + it("transcodes ETC1S ktx2 to astc", function () { + return expectKTX2TranscodeResult( + "./Data/Images/Green4x4_ETC1S.ktx2", + { astc: true }, + 4, + 4, + true + ); + }); + + it("transcodes UASTC ktx2 to astc", function () { + return expectKTX2TranscodeResult( + "./Data/Images/Logo32x32_UASTC_Zstd.ktx2", + { astc: true }, + 32, + 32, + true + ); + }); + + it("transcodes ETC1S ktx2 to pvrtc", function () { + return expectKTX2TranscodeResult( + "./Data/Images/Green4x4_ETC1S.ktx2", + { pvrtc: true }, + 4, + 4, + true + ); + }); + + it("transcodes UASTC ktx2 to pvrtc", function () { + return expectKTX2TranscodeResult( + "./Data/Images/Logo32x32_UASTC_Zstd.ktx2", + { pvrtc: true }, + 32, + 32, + true + ); + }); + + it("transcodes ETC1S ktx2 to s3tc", function () { + return expectKTX2TranscodeResult( + "./Data/Images/Green4x4_ETC1S.ktx2", + { s3tc: true }, + 4, + 4, + true + ); + }); + + it("transcodes UASTC ktx2 to s3tc", function () { + return expectKTX2TranscodeResult( + "./Data/Images/Logo32x32_UASTC_Zstd.ktx2", + { s3tc: true }, + 32, + 32, + true + ); + }); + + it("transcodes ETC1S ktx2 to bc7", function () { + return expectKTX2TranscodeResult( + "./Data/Images/Green4x4_ETC1S.ktx2", + { bc7: true }, + 4, + 4, + true + ); + }); + + it("transcodes UASTC ktx2 to bc7", function () { + return expectKTX2TranscodeResult( + "./Data/Images/Logo32x32_UASTC_Zstd.ktx2", + { bc7: true }, + 32, + 32, + true + ); + }); + + it("returns a promise that resolves to an uncompressed texture", function () { + return expectKTX2TranscodeResult( + "./Data/Images/Green4x4.ktx2", + { s3tc: true }, + 4, + 4, + false + ); + }); + + it("returns a promise that resolves to an uncompressed texture containing all mip levels of the original texture", function () { + var resource = Resource.createIfNeeded("./Data/Images/Green4x4Mipmap.ktx2"); + var loadPromise = resource.fetchArrayBuffer(); + return loadPromise.then(function (buffer) { + var promise = KTX2Transcoder.transcode(buffer, {}); + return promise.then(function (resolvedValue) { + expect(resolvedValue).toBeDefined(); + expect(resolvedValue.length).toEqual(3); + var dims = [4, 2, 1]; + for (var i = 0; i < resolvedValue.length; ++i) { + expect(resolvedValue[i].width).toEqual(dims[i]); + expect(resolvedValue[i].height).toEqual(dims[i]); + expect( + PixelFormat.isCompressedFormat(resolvedValue[i].internalFormat) + ).toEqual(false); + expect(resolvedValue[i].bufferView).toBeDefined(); + } + }); + }); + }); + + it("returns a promise that resolves to a compressed texture containing all mip levels of the original texture", function () { + var resource = Resource.createIfNeeded( + "./Data/Images/Green4x4Mipmap_ETC1S.ktx2" + ); + var loadPromise = resource.fetchArrayBuffer(); + return loadPromise.then(function (buffer) { + var promise = KTX2Transcoder.transcode(buffer, { etc1: true }); + return promise.then(function (resolvedValue) { + expect(resolvedValue).toBeDefined(); + expect(resolvedValue.length).toEqual(3); + var dims = [4, 2, 1]; + for (var i = 0; i < resolvedValue.length; ++i) { + expect(resolvedValue[i].width).toEqual(dims[i]); + expect(resolvedValue[i].height).toEqual(dims[i]); + expect( + PixelFormat.isCompressedFormat(resolvedValue[i].internalFormat) + ).toEqual(true); + expect(resolvedValue[i].bufferView).toBeDefined(); + } + }); + }); + }); + + it("cannot parse invalid KTX2 buffer", function () { + var invalidKTX = new Uint8Array([0, 1, 2, 3, 4, 5]); + var resolvedValue; + var rejectedError; + var promise = loadKTX2(invalidKTX.buffer); + return promise + .then(function (value) { + fail(); + }) + .otherwise(function (error) { + rejectedError = error; + expect(resolvedValue).toBeUndefined(); + expect(rejectedError).toBeInstanceOf(RuntimeError); + expect(rejectedError.message).toEqual("Invalid KTX2 file."); + }); + }); + + it("3D textures are unsupported", function () { + var resource = Resource.createIfNeeded("./Data/Images/Green4x4.ktx2"); + var loadPromise = resource.fetchArrayBuffer(); + return loadPromise.then(function (buffer) { + var invalidKTX = new Uint32Array(buffer); + invalidKTX[7] = 2; // Uint32 pixelDepth + + var resolvedValue; + var rejectedError; + var promise = loadKTX2(invalidKTX.buffer); + return promise + .then(function (value) { + fail(); + }) + .otherwise(function (error) { + rejectedError = error; + expect(resolvedValue).toBeUndefined(); + expect(rejectedError).toBeInstanceOf(RuntimeError); + expect(rejectedError.message).toEqual( + "KTX2 3D textures are unsupported." + ); + }); + }); + }); + + it("texture arrays are unsupported", function () { + var resource = Resource.createIfNeeded("./Data/Images/Green4x4.ktx2"); + var loadPromise = resource.fetchArrayBuffer(); + return loadPromise.then(function (buffer) { + var invalidKTX = new Uint32Array(buffer); + invalidKTX[8] = 15; // Uint32 layerCount + + var resolvedValue; + var rejectedError; + var promise = loadKTX2(invalidKTX.buffer); + return promise + .then(function (value) { + fail(); + }) + .otherwise(function (error) { + rejectedError = error; + expect(resolvedValue).toBeUndefined(); + expect(rejectedError).toBeInstanceOf(RuntimeError); + expect(rejectedError.message).toEqual( + "KTX2 texture arrays are not supported." + ); + }); + }); + }); +}); diff --git a/Specs/Core/loadKTXSpec.js b/Specs/Core/loadKTXSpec.js deleted file mode 100644 index 661bc66bab23..000000000000 --- a/Specs/Core/loadKTXSpec.js +++ /dev/null @@ -1,1080 +0,0 @@ -import { loadKTX } from "../../Source/Cesium.js"; -import { PixelFormat } from "../../Source/Cesium.js"; -import { Request } from "../../Source/Cesium.js"; -import { RequestErrorEvent } from "../../Source/Cesium.js"; -import { RequestScheduler } from "../../Source/Cesium.js"; -import { Resource } from "../../Source/Cesium.js"; -import { RuntimeError } from "../../Source/Cesium.js"; - -describe("Core/loadKTX", function () { - var validCompressed = new Uint8Array([ - 171, - 75, - 84, - 88, - 32, - 49, - 49, - 187, - 13, - 10, - 26, - 10, - 1, - 2, - 3, - 4, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 241, - 131, - 0, - 0, - 8, - 25, - 0, - 0, - 4, - 0, - 0, - 0, - 4, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8, - 0, - 0, - 0, - 224, - 7, - 224, - 7, - 0, - 0, - 0, - 0, - ]); - var validCompressedMipmap = new Uint8Array([ - 171, - 75, - 84, - 88, - 32, - 49, - 49, - 187, - 13, - 10, - 26, - 10, - 1, - 2, - 3, - 4, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 100, - 141, - 0, - 0, - 7, - 25, - 0, - 0, - 4, - 0, - 0, - 0, - 4, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 3, - 0, - 0, - 0, - 52, - 0, - 0, - 0, - 19, - 0, - 0, - 0, - 67, - 82, - 78, - 76, - 73, - 66, - 95, - 70, - 79, - 85, - 82, - 67, - 67, - 0, - 69, - 84, - 67, - 49, - 0, - 0, - 23, - 0, - 0, - 0, - 75, - 84, - 88, - 111, - 114, - 105, - 101, - 110, - 116, - 97, - 116, - 105, - 111, - 110, - 0, - 83, - 61, - 114, - 44, - 84, - 61, - 100, - 0, - 0, - 8, - 0, - 0, - 0, - 255, - 0, - 0, - 0, - 255, - 255, - 0, - 0, - 8, - 0, - 0, - 0, - 255, - 0, - 0, - 0, - 255, - 255, - 0, - 0, - 8, - 0, - 0, - 0, - 255, - 0, - 0, - 0, - 255, - 255, - 0, - 0, - ]); - var validUncompressed = new Uint8Array([ - 171, - 75, - 84, - 88, - 32, - 49, - 49, - 187, - 13, - 10, - 26, - 10, - 1, - 2, - 3, - 4, - 1, - 20, - 0, - 0, - 1, - 0, - 0, - 0, - 8, - 25, - 0, - 0, - 88, - 128, - 0, - 0, - 8, - 25, - 0, - 0, - 4, - 0, - 0, - 0, - 4, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 32, - 0, - 0, - 0, - 27, - 0, - 0, - 0, - 75, - 84, - 88, - 79, - 114, - 105, - 101, - 110, - 116, - 97, - 116, - 105, - 111, - 110, - 0, - 83, - 61, - 114, - 44, - 84, - 61, - 100, - 44, - 82, - 61, - 105, - 0, - 0, - 64, - 0, - 0, - 0, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - 0, - 255, - ]); - var validUncompressedMipmap = new Uint8Array([ - 171, - 75, - 84, - 88, - 32, - 49, - 49, - 187, - 13, - 10, - 26, - 10, - 1, - 2, - 3, - 4, - 1, - 20, - 0, - 0, - 1, - 0, - 0, - 0, - 7, - 25, - 0, - 0, - 81, - 128, - 0, - 0, - 7, - 25, - 0, - 0, - 4, - 0, - 0, - 0, - 4, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 3, - 0, - 0, - 0, - 52, - 0, - 0, - 0, - 19, - 0, - 0, - 0, - 67, - 82, - 78, - 76, - 73, - 66, - 95, - 70, - 79, - 85, - 82, - 67, - 67, - 0, - 82, - 71, - 66, - 120, - 0, - 0, - 23, - 0, - 0, - 0, - 75, - 84, - 88, - 111, - 114, - 105, - 101, - 110, - 116, - 97, - 116, - 105, - 111, - 110, - 0, - 83, - 61, - 114, - 44, - 84, - 61, - 100, - 0, - 0, - 48, - 0, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 12, - 0, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 255, - 0, - 0, - 3, - 0, - 0, - 0, - 255, - 0, - 0, - 0, - ]); - - var fakeXHR; - - beforeEach(function () { - fakeXHR = jasmine.createSpyObj("XMLHttpRequest", [ - "send", - "open", - "setRequestHeader", - "abort", - "getAllResponseHeaders", - ]); - fakeXHR.simulateLoad = function (response) { - fakeXHR.simulateHttpResponse(200, response); - }; - fakeXHR.simulateError = function () { - fakeXHR.response = ""; - if (typeof fakeXHR.onerror === "function") { - fakeXHR.onerror(); - } - }; - fakeXHR.simulateHttpResponse = function (statusCode, response) { - fakeXHR.status = statusCode; - fakeXHR.response = response; - if (typeof fakeXHR.onload === "function") { - fakeXHR.onload(); - } - }; - - spyOn(window, "XMLHttpRequest").and.returnValue(fakeXHR); - }); - - it("throws with no url", function () { - expect(function () { - loadKTX(); - }).toThrowDeveloperError(); - }); - - it("creates and sends request without any custom headers", function () { - var testUrl = "http://example.invalid/testuri"; - loadKTX(testUrl); - - expect(fakeXHR.open).toHaveBeenCalledWith("GET", testUrl, true); - expect(fakeXHR.setRequestHeader).not.toHaveBeenCalled(); - expect(fakeXHR.send).toHaveBeenCalled(); - }); - - it("returns a promise that rejects when the request errors", function () { - var testUrl = "http://example.invalid/testuri"; - var promise = loadKTX(testUrl); - - expect(promise).toBeDefined(); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - - fakeXHR.simulateError(); - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeInstanceOf(RequestErrorEvent); - expect(rejectedError.statusCode).toBeUndefined(); - expect(rejectedError.response).toBeUndefined(); - }); - - it("returns a promise that rejects when the request results in an HTTP error code", function () { - var testUrl = "http://example.invalid/testuri"; - var promise = loadKTX(testUrl); - - expect(promise).toBeDefined(); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - - var error = "some error"; - fakeXHR.simulateHttpResponse(404, error); - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeInstanceOf(RequestErrorEvent); - expect(rejectedError.statusCode).toEqual(404); - expect(rejectedError.response).toEqual(error); - }); - - it("returns a promise that resolves with undefined when the status code is 204", function () { - var testUrl = "http://example.invalid/testuri"; - var promise = loadKTX(testUrl); - - expect(promise).toBeDefined(); - - var resolved = false; - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolved = true; - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - - fakeXHR.simulateHttpResponse(204); - expect(resolved).toBe(true); - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - }); - - it("returns a promise that resolves to an uncompressed texture when the request loads", function () { - var testUrl = "http://example.invalid/testuri"; - var promise = loadKTX(testUrl); - - expect(promise).toBeDefined(); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - - var response = validUncompressed.buffer; - fakeXHR.simulateLoad(response); - expect(resolvedValue).toBeDefined(); - expect(resolvedValue.width).toEqual(4); - expect(resolvedValue.height).toEqual(4); - expect( - PixelFormat.isCompressedFormat(resolvedValue.internalFormat) - ).toEqual(false); - expect(resolvedValue.bufferView).toBeDefined(); - expect(rejectedError).toBeUndefined(); - }); - - it("returns a promise that resolves to an uncompressed texture containing all mip levels of the original texture", function () { - var testUrl = "http://example.invalid/testuri"; - var promise = loadKTX(testUrl); - - expect(promise).toBeDefined(); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - - var response = validUncompressedMipmap.buffer; - fakeXHR.simulateLoad(response); - expect(resolvedValue).toBeDefined(); - expect(resolvedValue.length).toEqual(3); - expect(resolvedValue[0].width).toEqual(4); - expect(resolvedValue[0].height).toEqual(4); - expect( - PixelFormat.isCompressedFormat(resolvedValue[0].internalFormat) - ).toEqual(false); - expect(resolvedValue[0].bufferView).toBeDefined(); - expect(rejectedError).toBeUndefined(); - }); - - it("returns a promise that resolves to a compressed texture when the request loads", function () { - var testUrl = "http://example.invalid/testuri"; - var promise = loadKTX(testUrl); - - expect(promise).toBeDefined(); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - - var response = validCompressed.buffer; - fakeXHR.simulateLoad(response); - expect(resolvedValue).toBeDefined(); - expect(resolvedValue.width).toEqual(4); - expect(resolvedValue.height).toEqual(4); - expect( - PixelFormat.isCompressedFormat(resolvedValue.internalFormat) - ).toEqual(true); - expect(resolvedValue.bufferView).toBeDefined(); - expect(rejectedError).toBeUndefined(); - }); - - it("returns a promise that resolves to a compressed texture containing the all mip levels of the original texture", function () { - var testUrl = "http://example.invalid/testuri"; - var promise = loadKTX(testUrl); - - expect(promise).toBeDefined(); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeUndefined(); - - var response = validCompressedMipmap.buffer; - fakeXHR.simulateLoad(response); - expect(resolvedValue).toBeDefined(); - expect(resolvedValue.length).toEqual(3); - expect(resolvedValue[0].width).toEqual(4); - expect(resolvedValue[0].height).toEqual(4); - expect( - PixelFormat.isCompressedFormat(resolvedValue[0].internalFormat) - ).toEqual(true); - expect(resolvedValue[0].bufferView).toBeDefined(); - expect(rejectedError).toBeUndefined(); - }); - - it("cannot parse invalid KTX buffer", function () { - var invalidKTX = new Uint8Array(validCompressed); - invalidKTX[0] = 0; - - var promise = loadKTX(invalidKTX.buffer); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeInstanceOf(RuntimeError); - expect(rejectedError.message).toEqual("Invalid KTX file."); - }); - - it("cannot parse KTX buffer with invalid endianness", function () { - var reinterprestBuffer = new Uint32Array(validCompressed.buffer); - var invalidKTX = new Uint32Array(reinterprestBuffer); - invalidKTX[3] = 0x01020304; - - var promise = loadKTX(invalidKTX.buffer); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeInstanceOf(RuntimeError); - expect(rejectedError.message).toEqual("File is the wrong endianness."); - }); - - it("cannot parse KTX buffer with invalid internal format", function () { - var reinterprestBuffer = new Uint32Array(validCompressed.buffer); - var invalidKTX = new Uint32Array(reinterprestBuffer); - invalidKTX[7] = 0; - - var promise = loadKTX(invalidKTX.buffer); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeInstanceOf(RuntimeError); - expect(rejectedError.message).toEqual( - "glInternalFormat is not a valid format." - ); - }); - - it("cannot parse KTX buffer with compressed texture and invalid type", function () { - var reinterprestBuffer = new Uint32Array(validCompressed.buffer); - var invalidKTX = new Uint32Array(reinterprestBuffer); - invalidKTX[4] = 15; - - var promise = loadKTX(invalidKTX.buffer); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeInstanceOf(RuntimeError); - expect(rejectedError.message).toEqual( - "glType must be zero when the texture is compressed." - ); - }); - - it("cannot parse KTX buffer with compressed texture and invalid type size", function () { - var reinterprestBuffer = new Uint32Array(validCompressed.buffer); - var invalidKTX = new Uint32Array(reinterprestBuffer); - invalidKTX[5] = 15; - - var promise = loadKTX(invalidKTX.buffer); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeInstanceOf(RuntimeError); - expect(rejectedError.message).toEqual( - "The type size for compressed textures must be 1." - ); - }); - - it("cannot parse KTX buffer with uncompressed texture and base format is not the same as format", function () { - var reinterprestBuffer = new Uint32Array(validUncompressed.buffer); - var invalidKTX = new Uint32Array(reinterprestBuffer); - invalidKTX[8] = invalidKTX[6] + 1; - - var promise = loadKTX(invalidKTX.buffer); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeInstanceOf(RuntimeError); - expect(rejectedError.message).toEqual( - "The base internal format must be the same as the format for uncompressed textures." - ); - }); - - it("3D textures are unsupported", function () { - var reinterprestBuffer = new Uint32Array(validUncompressed.buffer); - var invalidKTX = new Uint32Array(reinterprestBuffer); - invalidKTX[11] = 15; - - var promise = loadKTX(invalidKTX.buffer); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeInstanceOf(RuntimeError); - expect(rejectedError.message).toEqual("3D textures are unsupported."); - }); - - it("texture arrays are unsupported", function () { - var reinterprestBuffer = new Uint32Array(validUncompressed.buffer); - var invalidKTX = new Uint32Array(reinterprestBuffer); - invalidKTX[12] = 15; - - var promise = loadKTX(invalidKTX.buffer); - - var resolvedValue; - var rejectedError; - promise.then( - function (value) { - resolvedValue = value; - }, - function (error) { - rejectedError = error; - } - ); - - expect(resolvedValue).toBeUndefined(); - expect(rejectedError).toBeInstanceOf(RuntimeError); - expect(rejectedError.message).toEqual("Texture arrays are unsupported."); - }); - - it("cubemaps are supported", function () { - var reinterprestBuffer = new Uint32Array(validUncompressed.buffer); - var cubemapKTX = new Uint32Array(reinterprestBuffer); - cubemapKTX[13] = 6; - - var promise = loadKTX(cubemapKTX.buffer); - - promise.then(function (value) { - expect(value).toBeDefined(); - }); - }); - - it("returns undefined if the request is throttled", function () { - var oldMaximumRequests = RequestScheduler.maximumRequests; - RequestScheduler.maximumRequests = 0; - - var promise = loadKTX( - new Resource({ - url: "http://example.invalid/testuri", - request: new Request({ - throttle: true, - }), - }) - ); - expect(promise).toBeUndefined(); - - RequestScheduler.maximumRequests = oldMaximumRequests; - }); -}); diff --git a/Specs/Data/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx b/Specs/Data/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx deleted file mode 100644 index 7a8880d04115..000000000000 Binary files a/Specs/Data/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx and /dev/null differ diff --git a/Specs/Data/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx2 b/Specs/Data/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx2 new file mode 100644 index 000000000000..ac10d770d05d Binary files /dev/null and b/Specs/Data/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx2 differ diff --git a/Specs/Data/Images/Green4x4.crn b/Specs/Data/Images/Green4x4.crn deleted file mode 100644 index d32561e1af30..000000000000 Binary files a/Specs/Data/Images/Green4x4.crn and /dev/null differ diff --git a/Specs/Data/Images/Green4x4.ktx b/Specs/Data/Images/Green4x4.ktx deleted file mode 100644 index b251f62c3f5e..000000000000 Binary files a/Specs/Data/Images/Green4x4.ktx and /dev/null differ diff --git a/Specs/Data/Images/Green4x4.ktx2 b/Specs/Data/Images/Green4x4.ktx2 new file mode 100644 index 000000000000..84ea605d76f7 Binary files /dev/null and b/Specs/Data/Images/Green4x4.ktx2 differ diff --git a/Specs/Data/Images/Green4x4DXT1.ktx b/Specs/Data/Images/Green4x4DXT1.ktx deleted file mode 100644 index 7d013e8d2e94..000000000000 Binary files a/Specs/Data/Images/Green4x4DXT1.ktx and /dev/null differ diff --git a/Specs/Data/Images/Green4x4ETC1.ktx b/Specs/Data/Images/Green4x4ETC1.ktx deleted file mode 100644 index d3d1123c0906..000000000000 Binary files a/Specs/Data/Images/Green4x4ETC1.ktx and /dev/null differ diff --git a/Specs/Data/Images/Green4x4Mipmap.ktx2 b/Specs/Data/Images/Green4x4Mipmap.ktx2 new file mode 100644 index 000000000000..fcd642886068 Binary files /dev/null and b/Specs/Data/Images/Green4x4Mipmap.ktx2 differ diff --git a/Specs/Data/Images/Green4x4Mipmap_ETC1S.ktx2 b/Specs/Data/Images/Green4x4Mipmap_ETC1S.ktx2 new file mode 100644 index 000000000000..7a53dacc0992 Binary files /dev/null and b/Specs/Data/Images/Green4x4Mipmap_ETC1S.ktx2 differ diff --git a/Specs/Data/Images/Green4x4PVR.ktx b/Specs/Data/Images/Green4x4PVR.ktx deleted file mode 100644 index c6fe6296866f..000000000000 Binary files a/Specs/Data/Images/Green4x4PVR.ktx and /dev/null differ diff --git a/Specs/Data/Images/Green4x4_ETC1S.ktx2 b/Specs/Data/Images/Green4x4_ETC1S.ktx2 new file mode 100644 index 000000000000..41f3bc467413 Binary files /dev/null and b/Specs/Data/Images/Green4x4_ETC1S.ktx2 differ diff --git a/Specs/Data/Images/Logo32x32_UASTC_Zstd.ktx2 b/Specs/Data/Images/Logo32x32_UASTC_Zstd.ktx2 new file mode 100644 index 000000000000..6a27bbc914e5 Binary files /dev/null and b/Specs/Data/Images/Logo32x32_UASTC_Zstd.ktx2 differ diff --git a/Specs/Data/Models/Box-Textured-CRN-Binary/CesiumTexturedBoxTest.glb b/Specs/Data/Models/Box-Textured-CRN-Binary/CesiumTexturedBoxTest.glb deleted file mode 100644 index 7e988e8b0210..000000000000 Binary files a/Specs/Data/Models/Box-Textured-CRN-Binary/CesiumTexturedBoxTest.glb and /dev/null differ diff --git a/Specs/Data/Models/Box-Textured-CRN-Embedded/CesiumTexturedBoxTest.gltf b/Specs/Data/Models/Box-Textured-CRN-Embedded/CesiumTexturedBoxTest.gltf deleted file mode 100644 index fa3a353d192c..000000000000 --- a/Specs/Data/Models/Box-Textured-CRN-Embedded/CesiumTexturedBoxTest.gltf +++ /dev/null @@ -1,276 +0,0 @@ -{ - "accessors": { - "accessor_21": { - "bufferView": "bufferView_1", - "byteOffset": 0, - "byteStride": 0, - "componentType": 5123, - "count": 36, - "type": "SCALAR" - }, - "accessor_23": { - "bufferView": "bufferView_0", - "byteOffset": 0, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 0.5, - 0.5, - 0.5 - ], - "min": [ - -0.5, - -0.5, - -0.5 - ], - "type": "VEC3" - }, - "accessor_25": { - "bufferView": "bufferView_0", - "byteOffset": 288, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 1, - 1, - 1 - ], - "min": [ - -1, - -1, - -1 - ], - "type": "VEC3" - }, - "accessor_27": { - "bufferView": "bufferView_0", - "byteOffset": 576, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 6, - 1 - ], - "min": [ - 0, - 0 - ], - "type": "VEC2" - } - }, - "animations": {}, - "asset": { - "generator": "collada2gltf@", - "premultipliedAlpha": true, - "profile": { - "api": "WebGL", - "version": "1.0.2" - }, - "version": "1.0" - }, - "bufferViews": { - "bufferView_0": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 768, - "byteOffset": 0, - "target": 34962 - }, - "bufferView_1": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 72, - "byteOffset": 768, - "target": 34963 - } - }, - "buffers": { - "CesiumTexturedBoxTest": { - "type": "arraybuffer", - "byteLength": 840, - "uri": "data:application/octet-stream;base64,AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAC/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAL8AAAC/AAAAPwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAADAQAAAAAAAAKBAAAAAAAAAwED+/38/AACgQP7/fz8AAIBAAAAAAAAAoEAAAAAAAACAQAAAgD8AAKBAAACAPwAAAEAAAAAAAACAPwAAAAAAAABAAACAPwAAgD8AAIA/AABAQAAAAAAAAIBAAAAAAAAAQEAAAIA/AACAQAAAgD8AAEBAAAAAAAAAAEAAAAAAAABAQAAAgD8AAABAAACAPwAAAAAAAAAAAAAAAP7/fz8AAIA/AAAAAAAAgD/+/38/AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUA" - } - }, - "images": { - "Image0001": { - "name": "Image0001", - "uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=", - "extras": { - "compressedImage3DTiles": { - "crunch": { - "uri": "data:image/crn;base64,SHgASvv9AAAFlRpEAIAAgAEBAAAAAAAAAAAAAAAAAAAAAABKAAC4AE8AAQIAASsAdAAAAAAAAAAAAAAAAAAAAAAAfQACLQAAAqoAgnAA0wxAxABM1vqhQR4PUQKytgIE4wGEEIIKAL7+GiFANAMaDWRm8ENz89/XXoAAISoXJZtVe3l4rbbF7curHPHoJCSQ0CIAAAEBY0beiq4JVXxed+SQIAAACxESaN1oA9c9CS3aVe2qkwrehDP/ze+bpWAFYklTaqqCb0KqBA7+55nw0ZYedBoAABoAIbauOQlkKCAQAAAAAsMsP/OPmOZ2z0mW5s+abbQAZppmemfv989/372AAMZsANtQQQUAUCt8JR7jEnnvtIma6DnKZIAEAWBgEoCAgA2I8sRAWMZ4DI9A9MPeNheAVzYPjtAb2D0Bz5sG0BAEAAWAsFtC3dTu6uFXBRdhbp4eWAjYCUoK0BYNNWG9Sgb8gVkgVjZTRCgwC6BSjSzkJkyIiItYldwXRaPWBh0I5Z9RsEAbchXcDPgHAKaFOFjHv+r1rWtZ/vIEz+oD+fu8Dt/a6a1rWLB1AOQLmr1rWqsBGBlIwbYGEcs47rFP004GOFHx2gO1gEBYg7LWPmeUCYgWEIbFd6EGOX146KId3s6WwEeg63YM9QFZ1DAGGgooAsU6ACwFuXy9PCkeOYwwCGzeT0hCwhS3LBoFKcXwDIVfa6vl9T7jqeA449vxfs+/+7Pzx+JW9AAG3m1QwgxRQABeX6Qhl7InpDEQRAEFdBCGglO4iAFGIwQhgIgudQl0qcq8qMqCoCfEChpBCDADfcB3CBMzKys2na1WzVtTZ8ywPkBTg/4B0mBREm2AAABfSDC8bnWouLmguCitlpS3qpduH5nYo/AuZvlVte5cnZc9c5SRCGa8AAPgAOBRaFjsvQc/o5XPe+EHC5rr8+5HdjNk52uhsy9LwAAAAAAKgAiuKMqubSqaZX00/owxhoAFhs9+jAm7F0fd5pyO2WKeQAAANAB10e5qr7y2uI9GGgAAAAgACWDHgzWzerutty7vAC8B0Zsyrvbd39M2wu+ILDhI8mNJXJ3QAAAABxAlVfs8fxh2YjqnTxgAI7nb3epejAAAAAAB1k8vTem//1Zky9Vm5a64wsI19t+p9aNkKdNFLRq7X4cGlS54qxPXAKx+yCc636HiVrHISRhYTyKXfN6drc8AysbVW0MgOF3218sP4Q2yzRFVT/3Ox4r4aEMunXywVobH/QQ81Hpnq3/x8MWjk93Ba1gAAAhYc5qsPn02EPNqx8z8Ps4bP5OrP/zQ44N0fEgs+aedyHL9fezU8m52bYNABsijLD2LBbetzfp1l6LvFhtvO4dmXVz8/ch2wA5Xe6l3FLupd9tveFEln5btr6m9Dr/tyenLQzxgHlGVyy1S1tPd/Oat/e+HPv17yHL3ZGKLnSTUoaKs0sbqpr3eHHhtdAvdnDbwYO9eHlr70evJokZVMNvltY++zm3VPjBP31EGdalm9i0vv+5te/XpqV/tRZMAH7IpoprMibLvbkk59P7QT1VEGdnR+8tHDQneIUdDsfPN6TJTxZLWmKn1zgAAADzBk10anTk8fyfZjtq/XXdfPbT6Z7WmFtqeKZA9RwSan9aGFn3wgBv9oInjk4uL25FNEkwuW3MgmY+GHMal4vZ/1E/QAAAAAUrbmeEU3f49vrq44xIB0qhkuU6OTY3nDWAAAAAAAABwAC2kcmpPVVPqjBeAAH3RTsliMqWYPNMMxBUAAAAACTAkb/GXY35+jg9qv4HXgoAIAAdKoZLn5E46f4bN+SaTgj5ZZ12ayJ7SYADwROsUGBZ6n+VelzR+nwkjF+8AAAAAHgAAGrngJavn/MB9K8HIe8+XlYpl1fkxDb0E5Y4CgAAAAA==" - } - } - } - } - }, - "materials": { - "Effect-Texture": { - "name": "Texture", - "technique": "technique0", - "values": { - "diffuse": "texture_Image0001", - "shininess": 256, - "specular": [ - 0.20000000298023224, - 0.20000000298023224, - 0.20000000298023224, - 1 - ] - } - } - }, - "meshes": { - "Geometry-mesh002": { - "name": "Mesh", - "primitives": [ - { - "attributes": { - "NORMAL": "accessor_25", - "POSITION": "accessor_23", - "TEXCOORD_0": "accessor_27" - }, - "indices": "accessor_21", - "material": "Effect-Texture", - "mode": 4 - } - ] - } - }, - "nodes": { - "rootNode": { - "children": [], - "meshes": [ - "Geometry-mesh002" - ], - "matrix": [ - 1, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 1 - ] - } - }, - "programs": { - "program_0": { - "attributes": [ - "a_normal", - "a_position", - "a_texcoord0" - ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" - } - }, - "samplers": { - "sampler_0": { - "magFilter": 9729, - "minFilter": 9729, - "wrapS": 10497, - "wrapT": 10497 - } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { - "nodes": [ - "rootNode" - ] - } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { - "type": 35632, - "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdmFyeWluZyB2ZWMzIHZfbm9ybWFsOw0KdmFyeWluZyB2ZWMyIHZfdGV4Y29vcmQwOw0KdW5pZm9ybSBzYW1wbGVyMkQgdV9kaWZmdXNlOw0KdW5pZm9ybSB2ZWM0IHVfc3BlY3VsYXI7DQp1bmlmb3JtIGZsb2F0IHVfc2hpbmluZXNzOw0Kdm9pZCBtYWluKHZvaWQpIHsNCnZlYzMgbm9ybWFsID0gbm9ybWFsaXplKHZfbm9ybWFsKTsNCnZlYzQgY29sb3IgPSB2ZWM0KDAuLCAwLiwgMC4sIDAuKTsNCnZlYzQgZGlmZnVzZSA9IHZlYzQoMC4sIDAuLCAwLiwgMS4pOw0KdmVjNCBzcGVjdWxhcjsNCmRpZmZ1c2UgPSB0ZXh0dXJlMkQodV9kaWZmdXNlLCB2X3RleGNvb3JkMCk7DQpzcGVjdWxhciA9IHVfc3BlY3VsYXI7DQpkaWZmdXNlLnh5eiAqPSBtYXgoZG90KG5vcm1hbCx2ZWMzKDAuLDAuLDEuKSksIDAuKTsNCmNvbG9yLnh5eiArPSBkaWZmdXNlLnh5ejsNCmNvbG9yID0gdmVjNChjb2xvci5yZ2IgKiBkaWZmdXNlLmEsIGRpZmZ1c2UuYSk7DQpnbF9GcmFnQ29sb3IgPSBjb2xvcjsNCn0NCg==" - }, - "CesiumTexturedBoxTest0VS": { - "type": 35633, - "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KYXR0cmlidXRlIHZlYzMgYV9wb3NpdGlvbjsNCmF0dHJpYnV0ZSB2ZWMzIGFfbm9ybWFsOw0KdmFyeWluZyB2ZWMzIHZfbm9ybWFsOw0KdW5pZm9ybSBtYXQzIHVfbm9ybWFsTWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfbW9kZWxWaWV3TWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfcHJvamVjdGlvbk1hdHJpeDsNCmF0dHJpYnV0ZSB2ZWMyIGFfdGV4Y29vcmQwOw0KdmFyeWluZyB2ZWMyIHZfdGV4Y29vcmQwOw0Kdm9pZCBtYWluKHZvaWQpIHsNCnZlYzQgcG9zID0gdV9tb2RlbFZpZXdNYXRyaXggKiB2ZWM0KGFfcG9zaXRpb24sMS4wKTsNCnZfbm9ybWFsID0gdV9ub3JtYWxNYXRyaXggKiBhX25vcm1hbDsNCnZfdGV4Y29vcmQwID0gYV90ZXhjb29yZDA7DQpnbF9Qb3NpdGlvbiA9IHVfcHJvamVjdGlvbk1hdHJpeCAqIHBvczsNCn0NCg==" - } - }, - "skins": {}, - "techniques": { - "technique0": { - "attributes": { - "a_normal": "normal", - "a_position": "position", - "a_texcoord0": "texcoord0" - }, - "parameters": { - "diffuse": { - "type": 35678 - }, - "modelViewMatrix": { - "semantic": "MODELVIEW", - "type": 35676 - }, - "normal": { - "semantic": "NORMAL", - "type": 35665 - }, - "normalMatrix": { - "semantic": "MODELVIEWINVERSETRANSPOSE", - "type": 35675 - }, - "position": { - "semantic": "POSITION", - "type": 35665 - }, - "projectionMatrix": { - "semantic": "PROJECTION", - "type": 35676 - }, - "shininess": { - "type": 5126 - }, - "specular": { - "type": 35666 - }, - "texcoord0": { - "semantic": "TEXCOORD_0", - "type": 35664 - } - }, - "program": "program_0", - "states": { - "enable": [ - 2929, - 2884 - ] - }, - "uniforms": { - "u_diffuse": "diffuse", - "u_modelViewMatrix": "modelViewMatrix", - "u_normalMatrix": "normalMatrix", - "u_projectionMatrix": "projectionMatrix", - "u_shininess": "shininess", - "u_specular": "specular" - } - } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 - } - }, - "cameras": {}, - "extensionsUsed": [] -} diff --git a/Specs/Data/Models/Box-Textured-CRN/CesiumTexturedBoxTest.gltf b/Specs/Data/Models/Box-Textured-CRN/CesiumTexturedBoxTest.gltf deleted file mode 100644 index 23be67a6fefb..000000000000 --- a/Specs/Data/Models/Box-Textured-CRN/CesiumTexturedBoxTest.gltf +++ /dev/null @@ -1,276 +0,0 @@ -{ - "accessors": { - "accessor_21": { - "bufferView": "bufferView_1", - "byteOffset": 0, - "byteStride": 0, - "componentType": 5123, - "count": 36, - "type": "SCALAR" - }, - "accessor_23": { - "bufferView": "bufferView_0", - "byteOffset": 0, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 0.5, - 0.5, - 0.5 - ], - "min": [ - -0.5, - -0.5, - -0.5 - ], - "type": "VEC3" - }, - "accessor_25": { - "bufferView": "bufferView_0", - "byteOffset": 288, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 1, - 1, - 1 - ], - "min": [ - -1, - -1, - -1 - ], - "type": "VEC3" - }, - "accessor_27": { - "bufferView": "bufferView_0", - "byteOffset": 576, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 6, - 1 - ], - "min": [ - 0, - 0 - ], - "type": "VEC2" - } - }, - "animations": {}, - "asset": { - "generator": "collada2gltf@", - "premultipliedAlpha": true, - "profile": { - "api": "WebGL", - "version": "1.0.2" - }, - "version": "1.0" - }, - "bufferViews": { - "bufferView_0": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 768, - "byteOffset": 0, - "target": 34962 - }, - "bufferView_1": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 72, - "byteOffset": 768, - "target": 34963 - } - }, - "buffers": { - "CesiumTexturedBoxTest": { - "type": "arraybuffer", - "byteLength": 840, - "uri": "data:application/octet-stream;base64,AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAC/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAL8AAAC/AAAAPwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAADAQAAAAAAAAKBAAAAAAAAAwED+/38/AACgQP7/fz8AAIBAAAAAAAAAoEAAAAAAAACAQAAAgD8AAKBAAACAPwAAAEAAAAAAAACAPwAAAAAAAABAAACAPwAAgD8AAIA/AABAQAAAAAAAAIBAAAAAAAAAQEAAAIA/AACAQAAAgD8AAEBAAAAAAAAAAEAAAAAAAABAQAAAgD8AAABAAACAPwAAAAAAAAAAAAAAAP7/fz8AAIA/AAAAAAAAgD/+/38/AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUA" - } - }, - "images": { - "Image0001": { - "name": "Image0001", - "uri": "Image0001.png", - "extras": { - "compressedImage3DTiles": { - "crunch": { - "uri": "Image0001-crunch.crn" - } - } - } - } - }, - "materials": { - "Effect-Texture": { - "name": "Texture", - "technique": "technique0", - "values": { - "diffuse": "texture_Image0001", - "shininess": 256, - "specular": [ - 0.20000000298023224, - 0.20000000298023224, - 0.20000000298023224, - 1 - ] - } - } - }, - "meshes": { - "Geometry-mesh002": { - "name": "Mesh", - "primitives": [ - { - "attributes": { - "NORMAL": "accessor_25", - "POSITION": "accessor_23", - "TEXCOORD_0": "accessor_27" - }, - "indices": "accessor_21", - "material": "Effect-Texture", - "mode": 4 - } - ] - } - }, - "nodes": { - "rootNode": { - "children": [], - "meshes": [ - "Geometry-mesh002" - ], - "matrix": [ - 1, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 1 - ] - } - }, - "programs": { - "program_0": { - "attributes": [ - "a_normal", - "a_position", - "a_texcoord0" - ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" - } - }, - "samplers": { - "sampler_0": { - "magFilter": 9729, - "minFilter": 9729, - "wrapS": 10497, - "wrapT": 10497 - } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { - "nodes": [ - "rootNode" - ] - } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { - "type": 35632, - "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdmFyeWluZyB2ZWMzIHZfbm9ybWFsOw0KdmFyeWluZyB2ZWMyIHZfdGV4Y29vcmQwOw0KdW5pZm9ybSBzYW1wbGVyMkQgdV9kaWZmdXNlOw0KdW5pZm9ybSB2ZWM0IHVfc3BlY3VsYXI7DQp1bmlmb3JtIGZsb2F0IHVfc2hpbmluZXNzOw0Kdm9pZCBtYWluKHZvaWQpIHsNCnZlYzMgbm9ybWFsID0gbm9ybWFsaXplKHZfbm9ybWFsKTsNCnZlYzQgY29sb3IgPSB2ZWM0KDAuLCAwLiwgMC4sIDAuKTsNCnZlYzQgZGlmZnVzZSA9IHZlYzQoMC4sIDAuLCAwLiwgMS4pOw0KdmVjNCBzcGVjdWxhcjsNCmRpZmZ1c2UgPSB0ZXh0dXJlMkQodV9kaWZmdXNlLCB2X3RleGNvb3JkMCk7DQpzcGVjdWxhciA9IHVfc3BlY3VsYXI7DQpkaWZmdXNlLnh5eiAqPSBtYXgoZG90KG5vcm1hbCx2ZWMzKDAuLDAuLDEuKSksIDAuKTsNCmNvbG9yLnh5eiArPSBkaWZmdXNlLnh5ejsNCmNvbG9yID0gdmVjNChjb2xvci5yZ2IgKiBkaWZmdXNlLmEsIGRpZmZ1c2UuYSk7DQpnbF9GcmFnQ29sb3IgPSBjb2xvcjsNCn0NCg==" - }, - "CesiumTexturedBoxTest0VS": { - "type": 35633, - "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KYXR0cmlidXRlIHZlYzMgYV9wb3NpdGlvbjsNCmF0dHJpYnV0ZSB2ZWMzIGFfbm9ybWFsOw0KdmFyeWluZyB2ZWMzIHZfbm9ybWFsOw0KdW5pZm9ybSBtYXQzIHVfbm9ybWFsTWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfbW9kZWxWaWV3TWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfcHJvamVjdGlvbk1hdHJpeDsNCmF0dHJpYnV0ZSB2ZWMyIGFfdGV4Y29vcmQwOw0KdmFyeWluZyB2ZWMyIHZfdGV4Y29vcmQwOw0Kdm9pZCBtYWluKHZvaWQpIHsNCnZlYzQgcG9zID0gdV9tb2RlbFZpZXdNYXRyaXggKiB2ZWM0KGFfcG9zaXRpb24sMS4wKTsNCnZfbm9ybWFsID0gdV9ub3JtYWxNYXRyaXggKiBhX25vcm1hbDsNCnZfdGV4Y29vcmQwID0gYV90ZXhjb29yZDA7DQpnbF9Qb3NpdGlvbiA9IHVfcHJvamVjdGlvbk1hdHJpeCAqIHBvczsNCn0NCg==" - } - }, - "skins": {}, - "techniques": { - "technique0": { - "attributes": { - "a_normal": "normal", - "a_position": "position", - "a_texcoord0": "texcoord0" - }, - "parameters": { - "diffuse": { - "type": 35678 - }, - "modelViewMatrix": { - "semantic": "MODELVIEW", - "type": 35676 - }, - "normal": { - "semantic": "NORMAL", - "type": 35665 - }, - "normalMatrix": { - "semantic": "MODELVIEWINVERSETRANSPOSE", - "type": 35675 - }, - "position": { - "semantic": "POSITION", - "type": 35665 - }, - "projectionMatrix": { - "semantic": "PROJECTION", - "type": 35676 - }, - "shininess": { - "type": 5126 - }, - "specular": { - "type": 35666 - }, - "texcoord0": { - "semantic": "TEXCOORD_0", - "type": 35664 - } - }, - "program": "program_0", - "states": { - "enable": [ - 2929, - 2884 - ] - }, - "uniforms": { - "u_diffuse": "diffuse", - "u_modelViewMatrix": "modelViewMatrix", - "u_normalMatrix": "normalMatrix", - "u_projectionMatrix": "projectionMatrix", - "u_shininess": "shininess", - "u_specular": "specular" - } - } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 - } - }, - "cameras": {}, - "extensionsUsed": [] -} diff --git a/Specs/Data/Models/Box-Textured-CRN/Image0001-crunch.crn b/Specs/Data/Models/Box-Textured-CRN/Image0001-crunch.crn deleted file mode 100644 index ff524c5fb28c..000000000000 Binary files a/Specs/Data/Models/Box-Textured-CRN/Image0001-crunch.crn and /dev/null differ diff --git a/Specs/Data/Models/Box-Textured-CRN/Image0001.png b/Specs/Data/Models/Box-Textured-CRN/Image0001.png deleted file mode 100644 index 073fcf40a183..000000000000 Binary files a/Specs/Data/Models/Box-Textured-CRN/Image0001.png and /dev/null differ diff --git a/Specs/Data/Models/Box-Textured-KTX-Binary/CesiumTexturedBoxTest.glb b/Specs/Data/Models/Box-Textured-KTX-Binary/CesiumTexturedBoxTest.glb deleted file mode 100644 index ec4774259c3b..000000000000 Binary files a/Specs/Data/Models/Box-Textured-KTX-Binary/CesiumTexturedBoxTest.glb and /dev/null differ diff --git a/Specs/Data/Models/Box-Textured-KTX-Embedded/CesiumTexturedBoxTest.gltf b/Specs/Data/Models/Box-Textured-KTX-Embedded/CesiumTexturedBoxTest.gltf deleted file mode 100644 index 1b59277eb682..000000000000 --- a/Specs/Data/Models/Box-Textured-KTX-Embedded/CesiumTexturedBoxTest.gltf +++ /dev/null @@ -1,282 +0,0 @@ -{ - "accessors": { - "accessor_21": { - "bufferView": "bufferView_1", - "byteOffset": 0, - "byteStride": 0, - "componentType": 5123, - "count": 36, - "type": "SCALAR" - }, - "accessor_23": { - "bufferView": "bufferView_0", - "byteOffset": 0, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 0.5, - 0.5, - 0.5 - ], - "min": [ - -0.5, - -0.5, - -0.5 - ], - "type": "VEC3" - }, - "accessor_25": { - "bufferView": "bufferView_0", - "byteOffset": 288, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 1, - 1, - 1 - ], - "min": [ - -1, - -1, - -1 - ], - "type": "VEC3" - }, - "accessor_27": { - "bufferView": "bufferView_0", - "byteOffset": 576, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 6, - 1 - ], - "min": [ - 0, - 0 - ], - "type": "VEC2" - } - }, - "animations": {}, - "asset": { - "generator": "collada2gltf@", - "premultipliedAlpha": true, - "profile": { - "api": "WebGL", - "version": "1.0.2" - }, - "version": "1.0" - }, - "bufferViews": { - "bufferView_0": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 768, - "byteOffset": 0, - "target": 34962 - }, - "bufferView_1": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 72, - "byteOffset": 768, - "target": 34963 - } - }, - "buffers": { - "CesiumTexturedBoxTest": { - "type": "arraybuffer", - "byteLength": 840, - "uri": "data:application/octet-stream;base64,AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAC/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAL8AAAC/AAAAPwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAADAQAAAAAAAAKBAAAAAAAAAwED+/38/AACgQP7/fz8AAIBAAAAAAAAAoEAAAAAAAACAQAAAgD8AAKBAAACAPwAAAEAAAAAAAACAPwAAAAAAAABAAACAPwAAgD8AAIA/AABAQAAAAAAAAIBAAAAAAAAAQEAAAIA/AACAQAAAgD8AAEBAAAAAAAAAAEAAAAAAAABAQAAAgD8AAABAAACAPwAAAAAAAAAAAAAAAP7/fz8AAIA/AAAAAAAAgD/+/38/AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUA" - } - }, - "images": { - "Image0001": { - "name": "Image0001", - "uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=", - "extras": { - "compressedImage3DTiles": { - "s3tc": { - "uri": "data:image/ktx;base64,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qqqqqnttW2WAAIBA3/dbbSUNAQL//97/AAAAAP//DIUAAIBA//8CVFxWVVUlXCRcqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqkJ2gQx9////e9wJUAAIBDf//3/cAAAAA//87XWDAAAA913ttVVVVVFp1e21VX1VdvG3ZbKqqqqpadXttVdVVVZt9O1Wqquo6//87ZSUJAwD//9/3AgACAv//RGQAAIBgXOfjU1xWVVUlXCRcqqqqqmVkxEuqqqqqZWTES6qqqqoCVPveYGBgYPveutaqqqqr+9661qqqqqrb3nttWFBwcHttW22oqqqonG17bVVVVdXf93ttlTUFCf//3veIAAAA//+99wCAKEi+9+JTYFhUV0hsI1T+////ZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqoZsBFT///////8DVDWVVVX//+t8AAACAf//3veoAAAA//97bVhwQIB7bVtlAAACA7xt2Wyqqqqqm31bZf//v3/f93ttlSUNAf//3vcIAAAA//863wAAAEDf/wJUcFxWVUVcJFz4////ZWTES6qqqqplZMRLqqqqqkVcJVz//7+//N4DVCUlBQ383rjWqqqqqvveutaqqqqq2957bWBgQAA8phtV///9/P//W2VV1TUL//+9vgEAAAD//773AACAIP//AlTAYFhcR2QBVKGoqqqGbARU/////2VkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqpFXARcqqqqqkhsI1S/////3vcCVA0lFdX//3vnAAAAA///3/8ooAIC//97bVZccIA8pnttVVVVVv//e21VlSUL//9e3wEAAAD//773AACAIP//AlTAcFhWSGwjVPn+//9lZMRLqqqqqmVkxEuqqqqqZWTES6qqqqpHZAFUqiqqatrWAVQJCQED29761qioqqoc53jGqqqqqn33ms4///////893/gAAgP//9/3IyiAAP//vvcAAACA//9FZACAYFBwlaBD9P3//0VcBFyqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqqGbARU/////2dk4EtKKqqq3/8CVAMJJTXe9///VVVWWf//3/cggAAA//9+594AAAD//973IAoAAP//vvcAAACA//8CVADAYFiqdAJU9P3//yVkRUyqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqT43AQ3//vx9wlfveVFZVVRzneMaqqqqqHOd4xqqqqqr73rrWqqqqqv//+94BCQ0l///e9wAAoMD//wJUAABgXlznA1RcV1VVBWxEVP////9lZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqpIbCNU/////+6E4Esff///3vcDVAADJdX//xnXAAAAAf//AlQAAAAA//++9wAACED//+JLAIBgXvjWJVxUVVVVRVwEXKqqqqplZMRLqqqqqmVkxEuqqqqqRVwEXKqqqqpFXARcqqqqqtveA1SVNSUF/Oba1v7///8c53jGqqqqqhzneMaqqqqqHOd4xqqqqqqf/y+NCmrqqjvf4kvgV1VXR2QAVIWiqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqkdkAExKKqqq/N4DVC1VVVWd7wNUAP1VVfnW4kvgV1VVR2QAVIWoqqpIbCNU/////2VkxEuqqqqqZWTES6qqqqplZMRLqqqqqoRU5WOqqqqqR2QAVKqqSioiVNrWWFRWVdve+taqqKiqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqq/Oba1r/////83gJUVlxYcEhsI1T////+ZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqolXCRc+qqqqoVb5FyqqqqqRVwlXO////+EVOVjqqqqqoZsBFT/////ZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqpIbCNU////v9rWA1SVNSUN+9661qioqqoa33zeqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqtve+tYiqqqq296IbECAAADa1iJUVVVWXEdkAFSqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqoVb5Fyqqqqqmc4DVFVV1TX73mZkCQIAALjm/Nb/////HOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqvzm2tb/////295EXFBggABwlcBL///99CVcJFyqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqRVwEXKqqqqovjeBL//9/H9veIlwlCQIAut4816qqqqr85trW/////xzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqrb3vrWqqqqqrjm/Nb/////A1T73gkllVVwlcBD///99EdkAEyqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqpEXCVc////ew6F4Uv//38f294DVDUNAwDb3hrXgoIoqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqr85trW//////revNaqoqqq294jXFhgAACZzgNUVVVXWEZcJFz////+RVwlXP////9lZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqRlwkXP////+EVOVjqqqqqkhsI1T///+/V8YDVFVV1SX73iNcJQkCANve+taiqKqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqvveutaqqqqq296IbGAAAAD83gNUVVd4gIlsAlT///u0SGwjVP////9lZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqmVkxEuqqqqqZWTES6qqqqplZMRLqqqqqoZsBFT///+/R2QBVKqqihrb3gNUVdUtAtveRmQJAAAA+t681qqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqrveOteqqqqqPOe61r/////b3sBDeIAAANrWA1RVV3gAcZ3AQ////XhHZAFUqqqqDUhsI1T////6RVwEXKqqqqplZMRLqqqqqmVkxEuqqqqqSGwjVP////9FXCVc////q0dkAFSqqqpicJWgQ///fy+61gNUVdUtAANU295gVlVV/Oba1v7////b3vrWKqqqqrjm/Nb/////HOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqtve+taqKqqqfOYa1//////85trWv/////ve0qVgAAAA294CVF+gAADb3iNUVV+AANveI1xVVeoA+94DVFVV/wDb3gNUVVX/AAJUHecAAKpV294jXFX1AgDb3uFL9QoAALKl+95YVVVV+9661qiqqqp85hrX//////zm2tb/////HOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqtve+taqqqqquOb81v/////73rrWuqqqqtve+taogqqqfOYa1//////85trW//////veutaqqqqq/Oba1v////8c53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqoc53jGqqqqqhzneMaqqqqqHOd4xqqqqqo=" - }, - "etc1": { - "uri": "data:image/ktx;base64,q0tUWCAxMbsNChoKAQIDBAAAAAABAAAAAAAAAGSNAAAHGQAAgAAAAIAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAgAADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AAN3f2Au7s4AA2NvdCfu7AETG2t0hIiIiRKbK3YEiIgAAnMXYp+7uAACcxdin7u4AAKbK3YEiIgAAxtrdISIiRCLY290Ju79EAN3f2As7uwAI2NjYA///AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgD//8AANrc3Qn7s4jEpsrdQTIgIhV3qNgCEe4AAWaq3QAAAAAAZqrdAQAAAABmqt0BAAAAAGaq3QEAAAAAZqrdAQAAAABmqt0BAAAAAGaq3QEAAAAAZqrdAQAAAABpqNgC7iEQAKbK3UECI1Ei2dzdCTu/TIjY2NgC//8AANjY2AP//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANze2A/7M4AA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//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADd3twSEf8QEGuLOU33MUSOWI8oAgD3AAhYgCgCAAAAAFiAKAIAAAAAWIAoAgAAAABYgCgCAAAAAFiAKAIAAAAAWIAoAgAAAABYgCgCAAAAAFiAKAIAAAAAWIAoAgAAAABYgCgCAAAAAFiAKAIAAAAAWIAoAwAAAABYgSgDTMyAAGqLOS0Tf+hEvc29gczdAAHY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AALO7q4sxEBEAa4s6LXdxTIpujz5iAHcACFiAKAIAAAAAWIAoAwAAAABYgCgCAAAAAFiAKAIAAAAAWIAoAgAAAABYgCgCAAAAAFiAKAIAAAAAWIAoAgAAAABZgSoOdwCAAGuLKi0Xd6jEs7uriwETABHY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgD//8AANjY2AL//wAA3t/eChH/EBCdrX1h3d0TMm2NPEV90UACW4wqCUREzMhaiykZREQAAFqLKRlERAAAW4wqCUREjMxtjTwlXV8gRJ2tfWHd3SMRytHJQv8RAQHY2NgD//8AANjY2AP//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AP//wAA2NjYA///AADY2NgD//8AANjY2AP//wAA2NjYA///AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AANjY2AL//wAA2NjYAv//AADY2NgC//8AAA==" - }, - "pvrtc1": { - "uri": "data:image/ktx;base64,q0tUWCAxMbsNChoKAQIDBAAAAAABAAAAAAAAAAGMAAAHGQAAgAAAAIAAAAAAAAAAAAAAAAEAAAABAAAAIAAAABsAAABLVFhPcmllbnRhdGlvbgBTPXIsVD1kLFI9aQAAABAAAP/v/19673vv9/e/93rve+//36/teu9773///99673vv/f///3rve+/3f///eu977////39673vv3+//93rve+//+f+/eu977+v/9/9673vv/v//73vve+/+//z/e+977/7v//9773vvzv//+3vve+/+/+v/e+t87/7//z+7tnvv/+39v3rve+/v//f/eu977/////9673vv7f3//3rve++/9///eu977/7///9773vv7v/W/3vvfO/+//8/u7Z67+776f9773vv/j9/D7u2e+8uCwMAu7J77wAAQFS9stu+HgcHAb2ye+8CAAAAvbJb30CQ8PC7tru28PDw9Lu2u7b/9/v/eu977/7///9773vv/////3rve+/+//8/3b577/7/vx+7tnvzCgEAAL2yeu8eAQAAvbZ77wAAUJS9sru2/v///3vve+/+bwsAvbJ77/77//9773vv/gAAAL2ye+8AAOD0u7a8tvD0wv+7tru2AADv/7u2vLb+///8u7a7tgAAoOS9sru2MDTE+bu2u7YABc/wu7a7tvLw/w+7tru2+P7/87u2u7b+///zu7a7tg4Pzw+7tru2Pg///7u2u7by8B8Pu7a7tj4P3wC7tru2zv/8wLu2u7bw8D8Au7a7tjAA/wC7tru2AAAPD7u2u7YAAM8Au7a7tgAAAAC7tru2zv/z/Hvve+/+/+//e+977z4fPw+9tnvzDgcLA7uye+/+++r/e+987/7+/n77xnrvAgADAL2ye+8AAAAAu7b7ygBA4PC7try28PDA8Lu2u7bw/T/7u7a7tvr///+7tru28PDA8Lu2u7bA9PD0u7a7tv7/D/+7tru2/v//H7u2u7b+Pv4+vbZ7734/Pi+7tnvvABCQ8L22u7bg8ODwu7a8tj4fPx+7tnvvPh8/D7u2e+/AwKAgvba7tiDA4GC7tru2wD3N/7u2u7ay//tfu7a7tjIMMw+7tru2Lh8uALu2vLYyAAQPu7a7th4LLwC7try2AMDA4Luy///Q9PD8u7b///7//PC7tru2/P///7u2u7b+///wu7a7tv7z//+7tru2/v/AH7u2u7Y+Dy8Au7a8tv3+/wC6tru2AACg/7uy//8+DP/Pu7a7tj7///y7tru2AAAP/7u2u7b+/8//u7a7tm///wC6tru2AAACD7u2///////wura7tuDgoAC7try2QNDg+Luy///0/fz/u7b///7//////////v//DwOu///+//////v///4/Px8Frv//CgICACWu//8AABAABa4lrn5///+9tv///v///xHX//8AAAICvbL//wYHDw+9tv//+Pjw8AWu///AwAAABa7//z4///+7tv///v///937///+////e+977/8AAAC6tnvv///7/3rve+/+/ZAAvbJ77wAAoPO9tru2zMD/P7u2u7YAAC8Pu7a8tj4j/Py7tru2/v///3vve+/+///+27p77/7///9773vvf/+//3rve+/QgAAAvbZ77wAAPx+9sru2/v/8+L22e+/QwAAAu7Z77/7/Mw+7tru2Dg/w8Lu2u7b+///wu7a7tvDw/z+7tru28PA/QLu2u7ZwEAAAu7a7tgz/DAC7tru2AAAAQL22HM8+b8z/u7a7tv78P/+7tru2AAA7D7uyu7Y+H3xgu7a7tvz/MAC7tru2AAB8/7u2//9+v89Qu7a7thBUQAC7ttu+//f/8nrve+/+P///e+977//ff/9673vv9/t+/3rve+9/jw//eu977/7//v27unvv/v///3vve+/+////e+977//r//9673vv/////3rve+////f6eu977//3//d673vv/v8//3vve+/+///+e+977//v//9673vv/f///3rve+/w8MDAu7Z77wAAAQG9tty+/u9f/3vve+/+//z8u7Z77xQEPwy7tru2Ph45BLu2u7bw8MDAu7Z784AAAAC6tlzf/v8//3vve+/+////e+977/d/999673vv97///3rve+/+////e+977/7//f+9snvv/s//z3vve+/+////e+977wAAMA+7tru2Pg88D7u2u7aAwMDAurb//8DAwMC7tv//Pg8zH7u2u7Y6H/70u7a7tgAAAAC7tn7fAADP/7u2u7b+//////////7/////////AgADA7u2//8CAwMAu7b///4/FAC7tv//AAD/v7q2u7YAAAAAvbIdxwBQD/+7tru28PDA8Lu2u7bw8PDwu7a7tv78/w+7tru2PA//D7u2u7bgoKAAu7bctgAAAwO7sv//Dg/KBLu2u7YAAAAAu7a7uv7/PwC7tru2MAD/8Lu2u7b+z7zwu7a7tvDw/x+7tru28PD/w7u2u7b8/HAcu7a7tj4PDwa7tru2LgYqALu2vLYwYMDwu7a7tsDwwPC7tru2AAAHC7u2vLY+Cz8Pu7a8tvDwxLW7tru2NA4AD7u2u7Y6Dz8Gu7a7thQAFQC9trq+/Pzw9Luye/Pg8MDAu7Z77/7/3/9773vvzs8PH3vve++AwABAu7Z77wAApP+7tv//bv/vmnvve+9KlkaVe+//+z4PHw+7try2KAopALu2vLZA4OD4u7b///j+/f+7tv//AMDA4Lu2///g9PT8vbb///7///+78////j8/DwWu///+//////////7//w8Fsv//QpBDknvv//9Wl5urd+f//wYBAQAFrv//AAAwEAOqBa7o/PT8Ja577/T89PwFrnzvPh8/H7u2e+8+Hz8vvbJ773AQIAC7try2MAAgBLu2vLY+Pz8/vbJ7774/v7+9tnvvIAQgAL22u7YAQEDQu7b//wAAAIC7tp7ngMDA8Lu2///8////u7b///7//z9pvv//8Pz8/7u2///+////fd///34vLw8lrv//DgMDAAWu//++qwsLe++99woLP69773vv/v///733///8//z+e+///77//v9773vv/v/z/3vve+++Aw8LBaq99y4PPz8Frnzv/r//PyWu//8+CwsABa7//wAAAAADqozCAEDw8AWuBK4AAFBQBa4kspCQkAADrgWu8PTB/AWuBK7O/wbwBa4Erh4LCwMFrv//AgAAACWq//8gELCwBa4ErvDw8DAFrgSuAABQkCWuBbJQkJDwBa4krvD09v0FrgSu/v/P8wWuBK4AABoKBa4lsi4PDw8FrgSu/P78/AWu///w8MDABa7//z4PDw8FrgSuDh8/DwWuBK5AgAAABa7//wAAPA8FrgSucDAABAWuBK4ADc/zBa4ErsLwwAAFrgSuMAA//wWuBK7+//zzBa4Erv7//P8FrgSu/v/P/wWuBK7O/w8PBa4Erj4PADAFrgSu8PDf/wWuBK48AwADBa4ErgIPfx8FrgSu/v///wWuBK7+/wDwBa4Ern5/D/8FrgSu/v/wPwWuBK7+///8e+977/7//+9773vvf////yaye+/+/+//e+97777///9773vv9/3//3rve+/+////e+977/7/z/9773vvAAABAAWueesCAw8PBa5778DwAAAFrgSuAAAAAAWuBK4+P///Ba577/7/2fN773vvAAAAAAWuz84CAx8fBa577//9/f9673vv/f//v3rve+/+v///e+977/+/f/9673vv9//n/3rve+//////eu9779///99673vv/////3rve+/+////e+977/7/8/9773vvf////ySye+/+/9//e+977/7///9773vv///f/Xrve+/+////e+977//3//9673vv/v8AAAWuBK4AAMwJBa4Erg4PAAAFrgSuMAA/AAWuBK4wADDwBa4ErvDw8AAErgSuwAAAAwWuBK7////wBK4ErsDwwPAFrgSuwPMAAAWuBK7+////Ba4Erv7/APAFrgSuMAAA8AWuBK7A8P/wBa4ErvDw8P8FrgSu/v//PwWuBK4AAAMLJa577z6///8FrnzvAAAAAAWuBK4AAAcLBa577/7/7v9773vv7v//83vve+/+////r8p87/7///9773vvwPDwxAWuBK4wEEAABa4krv7/z/8FrgSu//78AASuBK4AC///Ba577/7/7vd773vvAABW/wWum+///57/eu977w4PPz+7tv//vn///722///w8JAAu7a8sgAAAAG8sr7v/////ka2///8/PD0Ba7//wIDDw+9sv//Lh9/v72y//8ODwkJu7a7tjAEMAC7try2AAAAwL2y3/eA4NDwu7b//yAAEAC7try2AICA4Lu2///w/Pz/u7b///7///+f6///0NCAwCWu//8AAAAABa5puv7/z////////v/89AWq//8ABQwPBa4ErjIf8/8FrgSugAAAAAWqmOsAAP//Ba4Ervr///+/9////v/////////+f78vBa7//y4LBwAjrv//bgAAAAWu3vsAAP//BK4ErgAAkKQFrgWu0PT//AWuBK78////u7b///7//z8Fsv//HgcLAgWu//8CAAAAJa7d+34fLwsjrv//DgMDAAWu//8AAJBgBa4kqtDwMGAFrgSuMAAwAAWuBK4wAAAABa4ErvD89PwFrnvv9Pz0/AWue+8ABAIPBa4ErhIEEAAFrgWu+Pz8/AWue+/8//z/Ba577wAAAAAlrmm+AFDg8AWuJa4AEAAJBa4ErgQJOw8FrgSu8PTO/wWuBK7OP88fBa4Erj4APw8FrgSuPg8jAAWuBK4AAABABa6MwgDAQMAFqnvv/P///2vCe+/+/7//e+9778Dw0PAlrnvv8Pz4/QWqfO/u76/ve+987+7///9773vv/v///wWuBK7O/wD/Ba4Erv7///8FrgSu/v/AzwWuBK7y////Ba4Erv7/D/8FrgSuzv8D/wWuBK7+//D/Ba4Erv7///8FrgSuPv8/DwWuBK7+////Ba4Erv7/wGAFrgSuPg/A/wWuBK4O/w8fBa4ErnATAA8FrgSuHx8fAASuBK7+//P/Ba4Erv/v/wAErgSuPg8PHwWuBK4YChkABa4FrgAAVf8Frnzv/v+q/3vve+8B9P7/Ba577/7/6v9773vvJAsaACWuBa4AAID0Ba577wBAgPAFrnvv9P///wWufO/8////rcp87/7/Ps9773vv/v+fr3vve+8O/8//e+977w4PDw8FrgSuPg8vAQWuBa4AAADAJa5X54Dg0PQFrnzvAAAAQAWujMKA4OD8Ba577/T9/f8Frnvv/v+vr3vvfO/8////Ba587/7/n+9773zv/v/P/3vve+/+//3Pe+977+7/P/9773vv/v/+/3vve+/+/z/ze+977//3//9673vv/P///wWyfO/+/+//e+97767///9773vv/v/7P3vve+////z+eu977/4///9773vv///933rve+////n7eu977///v79673vv//+z/3rve+//99//eu9779+//vd673vv/////3rve+/f+t//eu977/////9673vv/////3rve+8=" - } - } - } - } - }, - "materials": { - "Effect-Texture": { - "name": "Texture", - "technique": "technique0", - "values": { - "diffuse": "texture_Image0001", - "shininess": 256, - "specular": [ - 0.20000000298023224, - 0.20000000298023224, - 0.20000000298023224, - 1 - ] - } - } - }, - "meshes": { - "Geometry-mesh002": { - "name": "Mesh", - "primitives": [ - { - "attributes": { - "NORMAL": "accessor_25", - "POSITION": "accessor_23", - "TEXCOORD_0": "accessor_27" - }, - "indices": "accessor_21", - "material": "Effect-Texture", - "mode": 4 - } - ] - } - }, - "nodes": { - "rootNode": { - "children": [], - "meshes": [ - "Geometry-mesh002" - ], - "matrix": [ - 1, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 1 - ] - } - }, - "programs": { - "program_0": { - "attributes": [ - "a_normal", - "a_position", - "a_texcoord0" - ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" - } - }, - "samplers": { - "sampler_0": { - "magFilter": 9729, - "minFilter": 9729, - "wrapS": 10497, - "wrapT": 10497 - } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { - "nodes": [ - "rootNode" - ] - } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { - "type": 35632, - "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdmFyeWluZyB2ZWMzIHZfbm9ybWFsOw0KdmFyeWluZyB2ZWMyIHZfdGV4Y29vcmQwOw0KdW5pZm9ybSBzYW1wbGVyMkQgdV9kaWZmdXNlOw0KdW5pZm9ybSB2ZWM0IHVfc3BlY3VsYXI7DQp1bmlmb3JtIGZsb2F0IHVfc2hpbmluZXNzOw0Kdm9pZCBtYWluKHZvaWQpIHsNCnZlYzMgbm9ybWFsID0gbm9ybWFsaXplKHZfbm9ybWFsKTsNCnZlYzQgY29sb3IgPSB2ZWM0KDAuLCAwLiwgMC4sIDAuKTsNCnZlYzQgZGlmZnVzZSA9IHZlYzQoMC4sIDAuLCAwLiwgMS4pOw0KdmVjNCBzcGVjdWxhcjsNCmRpZmZ1c2UgPSB0ZXh0dXJlMkQodV9kaWZmdXNlLCB2X3RleGNvb3JkMCk7DQpzcGVjdWxhciA9IHVfc3BlY3VsYXI7DQpkaWZmdXNlLnh5eiAqPSBtYXgoZG90KG5vcm1hbCx2ZWMzKDAuLDAuLDEuKSksIDAuKTsNCmNvbG9yLnh5eiArPSBkaWZmdXNlLnh5ejsNCmNvbG9yID0gdmVjNChjb2xvci5yZ2IgKiBkaWZmdXNlLmEsIGRpZmZ1c2UuYSk7DQpnbF9GcmFnQ29sb3IgPSBjb2xvcjsNCn0NCg==" - }, - "CesiumTexturedBoxTest0VS": { - "type": 35633, - "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KYXR0cmlidXRlIHZlYzMgYV9wb3NpdGlvbjsNCmF0dHJpYnV0ZSB2ZWMzIGFfbm9ybWFsOw0KdmFyeWluZyB2ZWMzIHZfbm9ybWFsOw0KdW5pZm9ybSBtYXQzIHVfbm9ybWFsTWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfbW9kZWxWaWV3TWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfcHJvamVjdGlvbk1hdHJpeDsNCmF0dHJpYnV0ZSB2ZWMyIGFfdGV4Y29vcmQwOw0KdmFyeWluZyB2ZWMyIHZfdGV4Y29vcmQwOw0Kdm9pZCBtYWluKHZvaWQpIHsNCnZlYzQgcG9zID0gdV9tb2RlbFZpZXdNYXRyaXggKiB2ZWM0KGFfcG9zaXRpb24sMS4wKTsNCnZfbm9ybWFsID0gdV9ub3JtYWxNYXRyaXggKiBhX25vcm1hbDsNCnZfdGV4Y29vcmQwID0gYV90ZXhjb29yZDA7DQpnbF9Qb3NpdGlvbiA9IHVfcHJvamVjdGlvbk1hdHJpeCAqIHBvczsNCn0NCg==" - } - }, - "skins": {}, - "techniques": { - "technique0": { - "attributes": { - "a_normal": "normal", - "a_position": "position", - "a_texcoord0": "texcoord0" - }, - "parameters": { - "diffuse": { - "type": 35678 - }, - "modelViewMatrix": { - "semantic": "MODELVIEW", - "type": 35676 - }, - "normal": { - "semantic": "NORMAL", - "type": 35665 - }, - "normalMatrix": { - "semantic": "MODELVIEWINVERSETRANSPOSE", - "type": 35675 - }, - "position": { - "semantic": "POSITION", - "type": 35665 - }, - "projectionMatrix": { - "semantic": "PROJECTION", - "type": 35676 - }, - "shininess": { - "type": 5126 - }, - "specular": { - "type": 35666 - }, - "texcoord0": { - "semantic": "TEXCOORD_0", - "type": 35664 - } - }, - "program": "program_0", - "states": { - "enable": [ - 2929, - 2884 - ] - }, - "uniforms": { - "u_diffuse": "diffuse", - "u_modelViewMatrix": "modelViewMatrix", - "u_normalMatrix": "normalMatrix", - "u_projectionMatrix": "projectionMatrix", - "u_shininess": "shininess", - "u_specular": "specular" - } - } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 - } - }, - "cameras": {}, - "extensionsUsed": [] -} diff --git a/Specs/Data/Models/Box-Textured-KTX/CesiumTexturedBoxTest.gltf b/Specs/Data/Models/Box-Textured-KTX/CesiumTexturedBoxTest.gltf deleted file mode 100644 index bc2dae588970..000000000000 --- a/Specs/Data/Models/Box-Textured-KTX/CesiumTexturedBoxTest.gltf +++ /dev/null @@ -1,282 +0,0 @@ -{ - "accessors": { - "accessor_21": { - "bufferView": "bufferView_1", - "byteOffset": 0, - "byteStride": 0, - "componentType": 5123, - "count": 36, - "type": "SCALAR" - }, - "accessor_23": { - "bufferView": "bufferView_0", - "byteOffset": 0, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 0.5, - 0.5, - 0.5 - ], - "min": [ - -0.5, - -0.5, - -0.5 - ], - "type": "VEC3" - }, - "accessor_25": { - "bufferView": "bufferView_0", - "byteOffset": 288, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 1, - 1, - 1 - ], - "min": [ - -1, - -1, - -1 - ], - "type": "VEC3" - }, - "accessor_27": { - "bufferView": "bufferView_0", - "byteOffset": 576, - "byteStride": 0, - "componentType": 5126, - "count": 24, - "max": [ - 6, - 1 - ], - "min": [ - 0, - 0 - ], - "type": "VEC2" - } - }, - "animations": {}, - "asset": { - "generator": "collada2gltf@", - "premultipliedAlpha": true, - "profile": { - "api": "WebGL", - "version": "1.0.2" - }, - "version": "1.0" - }, - "bufferViews": { - "bufferView_0": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 768, - "byteOffset": 0, - "target": 34962 - }, - "bufferView_1": { - "buffer": "CesiumTexturedBoxTest", - "byteLength": 72, - "byteOffset": 768, - "target": 34963 - } - }, - "buffers": { - "CesiumTexturedBoxTest": { - "type": "arraybuffer", - "byteLength": 840, - "uri": "data:application/octet-stream;base64,AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAC/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAL8AAAC/AAAAPwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAADAQAAAAAAAAKBAAAAAAAAAwED+/38/AACgQP7/fz8AAIBAAAAAAAAAoEAAAAAAAACAQAAAgD8AAKBAAACAPwAAAEAAAAAAAACAPwAAAAAAAABAAACAPwAAgD8AAIA/AABAQAAAAAAAAIBAAAAAAAAAQEAAAIA/AACAQAAAgD8AAEBAAAAAAAAAAEAAAAAAAABAQAAAgD8AAABAAACAPwAAAAAAAAAAAAAAAP7/fz8AAIA/AAAAAAAAgD/+/38/AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUA" - } - }, - "images": { - "Image0001": { - "name": "Image0001", - "uri": "Image0001.png", - "extras": { - "compressedImage3DTiles": { - "s3tc": { - "uri": "Image0001-s3tc.ktx" - }, - "etc1": { - "uri": "Image0001-etc1.ktx" - }, - "pvrtc1": { - "uri": "Image0001-pvrtc1.ktx" - } - } - } - } - }, - "materials": { - "Effect-Texture": { - "name": "Texture", - "technique": "technique0", - "values": { - "diffuse": "texture_Image0001", - "shininess": 256, - "specular": [ - 0.20000000298023224, - 0.20000000298023224, - 0.20000000298023224, - 1 - ] - } - } - }, - "meshes": { - "Geometry-mesh002": { - "name": "Mesh", - "primitives": [ - { - "attributes": { - "NORMAL": "accessor_25", - "POSITION": "accessor_23", - "TEXCOORD_0": "accessor_27" - }, - "indices": "accessor_21", - "material": "Effect-Texture", - "mode": 4 - } - ] - } - }, - "nodes": { - "rootNode": { - "children": [], - "meshes": [ - "Geometry-mesh002" - ], - "matrix": [ - 1, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 1 - ] - } - }, - "programs": { - "program_0": { - "attributes": [ - "a_normal", - "a_position", - "a_texcoord0" - ], - "fragmentShader": "CesiumTexturedBoxTest0FS", - "vertexShader": "CesiumTexturedBoxTest0VS" - } - }, - "samplers": { - "sampler_0": { - "magFilter": 9729, - "minFilter": 9729, - "wrapS": 10497, - "wrapT": 10497 - } - }, - "scene": "defaultScene", - "scenes": { - "defaultScene": { - "nodes": [ - "rootNode" - ] - } - }, - "shaders": { - "CesiumTexturedBoxTest0FS": { - "type": 35632, - "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdmFyeWluZyB2ZWMzIHZfbm9ybWFsOw0KdmFyeWluZyB2ZWMyIHZfdGV4Y29vcmQwOw0KdW5pZm9ybSBzYW1wbGVyMkQgdV9kaWZmdXNlOw0KdW5pZm9ybSB2ZWM0IHVfc3BlY3VsYXI7DQp1bmlmb3JtIGZsb2F0IHVfc2hpbmluZXNzOw0Kdm9pZCBtYWluKHZvaWQpIHsNCnZlYzMgbm9ybWFsID0gbm9ybWFsaXplKHZfbm9ybWFsKTsNCnZlYzQgY29sb3IgPSB2ZWM0KDAuLCAwLiwgMC4sIDAuKTsNCnZlYzQgZGlmZnVzZSA9IHZlYzQoMC4sIDAuLCAwLiwgMS4pOw0KdmVjNCBzcGVjdWxhcjsNCmRpZmZ1c2UgPSB0ZXh0dXJlMkQodV9kaWZmdXNlLCB2X3RleGNvb3JkMCk7DQpzcGVjdWxhciA9IHVfc3BlY3VsYXI7DQpkaWZmdXNlLnh5eiAqPSBtYXgoZG90KG5vcm1hbCx2ZWMzKDAuLDAuLDEuKSksIDAuKTsNCmNvbG9yLnh5eiArPSBkaWZmdXNlLnh5ejsNCmNvbG9yID0gdmVjNChjb2xvci5yZ2IgKiBkaWZmdXNlLmEsIGRpZmZ1c2UuYSk7DQpnbF9GcmFnQ29sb3IgPSBjb2xvcjsNCn0NCg==" - }, - "CesiumTexturedBoxTest0VS": { - "type": 35633, - "uri": "data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KYXR0cmlidXRlIHZlYzMgYV9wb3NpdGlvbjsNCmF0dHJpYnV0ZSB2ZWMzIGFfbm9ybWFsOw0KdmFyeWluZyB2ZWMzIHZfbm9ybWFsOw0KdW5pZm9ybSBtYXQzIHVfbm9ybWFsTWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfbW9kZWxWaWV3TWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfcHJvamVjdGlvbk1hdHJpeDsNCmF0dHJpYnV0ZSB2ZWMyIGFfdGV4Y29vcmQwOw0KdmFyeWluZyB2ZWMyIHZfdGV4Y29vcmQwOw0Kdm9pZCBtYWluKHZvaWQpIHsNCnZlYzQgcG9zID0gdV9tb2RlbFZpZXdNYXRyaXggKiB2ZWM0KGFfcG9zaXRpb24sMS4wKTsNCnZfbm9ybWFsID0gdV9ub3JtYWxNYXRyaXggKiBhX25vcm1hbDsNCnZfdGV4Y29vcmQwID0gYV90ZXhjb29yZDA7DQpnbF9Qb3NpdGlvbiA9IHVfcHJvamVjdGlvbk1hdHJpeCAqIHBvczsNCn0NCg==" - } - }, - "skins": {}, - "techniques": { - "technique0": { - "attributes": { - "a_normal": "normal", - "a_position": "position", - "a_texcoord0": "texcoord0" - }, - "parameters": { - "diffuse": { - "type": 35678 - }, - "modelViewMatrix": { - "semantic": "MODELVIEW", - "type": 35676 - }, - "normal": { - "semantic": "NORMAL", - "type": 35665 - }, - "normalMatrix": { - "semantic": "MODELVIEWINVERSETRANSPOSE", - "type": 35675 - }, - "position": { - "semantic": "POSITION", - "type": 35665 - }, - "projectionMatrix": { - "semantic": "PROJECTION", - "type": 35676 - }, - "shininess": { - "type": 5126 - }, - "specular": { - "type": 35666 - }, - "texcoord0": { - "semantic": "TEXCOORD_0", - "type": 35664 - } - }, - "program": "program_0", - "states": { - "enable": [ - 2929, - 2884 - ] - }, - "uniforms": { - "u_diffuse": "diffuse", - "u_modelViewMatrix": "modelViewMatrix", - "u_normalMatrix": "normalMatrix", - "u_projectionMatrix": "projectionMatrix", - "u_shininess": "shininess", - "u_specular": "specular" - } - } - }, - "textures": { - "texture_Image0001": { - "format": 6408, - "internalFormat": 6408, - "sampler": "sampler_0", - "source": "Image0001", - "target": 3553, - "type": 5121 - } - }, - "cameras": {}, - "extensionsUsed": [] -} diff --git a/Specs/Data/Models/Box-Textured-KTX/Image0001-etc1.ktx b/Specs/Data/Models/Box-Textured-KTX/Image0001-etc1.ktx deleted file mode 100644 index b5672fe60686..000000000000 Binary files a/Specs/Data/Models/Box-Textured-KTX/Image0001-etc1.ktx and /dev/null differ diff --git a/Specs/Data/Models/Box-Textured-KTX/Image0001-pvrtc1.ktx b/Specs/Data/Models/Box-Textured-KTX/Image0001-pvrtc1.ktx deleted file mode 100644 index f67b26e49312..000000000000 Binary files a/Specs/Data/Models/Box-Textured-KTX/Image0001-pvrtc1.ktx and /dev/null differ diff --git a/Specs/Data/Models/Box-Textured-KTX/Image0001-s3tc.ktx b/Specs/Data/Models/Box-Textured-KTX/Image0001-s3tc.ktx deleted file mode 100644 index ae4d0f4eebc6..000000000000 Binary files a/Specs/Data/Models/Box-Textured-KTX/Image0001-s3tc.ktx and /dev/null differ diff --git a/Specs/Data/Models/Box-Textured-KTX/Image0001.png b/Specs/Data/Models/Box-Textured-KTX/Image0001.png deleted file mode 100644 index 073fcf40a183..000000000000 Binary files a/Specs/Data/Models/Box-Textured-KTX/Image0001.png and /dev/null differ diff --git a/Specs/Data/Models/Box-Textured-KTX2-Basis/CesiumTexturedBoxTest.gltf b/Specs/Data/Models/Box-Textured-KTX2-Basis/CesiumTexturedBoxTest.gltf new file mode 100644 index 000000000000..ace71e649673 --- /dev/null +++ b/Specs/Data/Models/Box-Textured-KTX2-Basis/CesiumTexturedBoxTest.gltf @@ -0,0 +1,205 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "extensionsUsed": [ + "KHR_texture_basisu" + ], + "extensionsRequired": [ + "KHR_texture_basisu" + ], + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1, + 0, + 0, + 0, + 0, + 0, + -1, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 1 + ] + }, + { + "mesh": 0 + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2, + "TEXCOORD_0": 3 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Mesh" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "max": [ + 23 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 288, + "componentType": 5126, + "count": 24, + "max": [ + 0.5, + 0.5, + 0.5 + ], + "min": [ + -0.5, + -0.5, + -0.5 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 6, + 1 + ], + "min": [ + 0, + 0 + ], + "type": "VEC2" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0, + "texCoord": 0 + }, + "metallicFactor": 0, + "baseColorFactor": [ + 1, + 1, + 1, + 1 + ], + "roughnessFactor": 1 + }, + "name": "Texture", + "emissiveFactor": [ + 0, + 0, + 0 + ], + "alphaMode": "OPAQUE", + "doubleSided": false + } + ], + "textures": [ + { + "extensions": { + "KHR_texture_basisu": { + "source": 0 + } + } + } + ], + "images": [ + { + "mimeType": "image/ktx2", + "name": "cesium_logo", + "bufferView": 3 + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 72, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 72, + "byteLength": 576, + "byteStride": 12, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 648, + "byteLength": 192, + "byteStride": 8, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 840, + "byteLength": 3559 + } + ], + "buffers": [ + { + "name": "box-textured-separate", + "byteLength": 4400, + "uri": "data:application/octet-stream;base64,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" + } + ] +} diff --git a/Specs/Data/Models/Box-Textured-KTX2-Mipmap/CheckerboardTexturedBoxTest.gltf b/Specs/Data/Models/Box-Textured-KTX2-Mipmap/CheckerboardTexturedBoxTest.gltf new file mode 100644 index 000000000000..c0f6db8afd10 --- /dev/null +++ b/Specs/Data/Models/Box-Textured-KTX2-Mipmap/CheckerboardTexturedBoxTest.gltf @@ -0,0 +1,205 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "extensionsUsed": [ + "KHR_texture_basisu" + ], + "extensionsRequired": [ + "KHR_texture_basisu" + ], + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1, + 0, + 0, + 0, + 0, + 0, + -1, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 1 + ] + }, + { + "mesh": 0 + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2, + "TEXCOORD_0": 3 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Mesh" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "max": [ + 23 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 288, + "componentType": 5126, + "count": 24, + "max": [ + 0.5, + 0.5, + 0.5 + ], + "min": [ + -0.5, + -0.5, + -0.5 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 6, + 1 + ], + "min": [ + 0, + 0 + ], + "type": "VEC2" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0, + "texCoord": 0 + }, + "metallicFactor": 0, + "baseColorFactor": [ + 1, + 1, + 1, + 1 + ], + "roughnessFactor": 1 + }, + "name": "Texture", + "emissiveFactor": [ + 0, + 0, + 0 + ], + "alphaMode": "OPAQUE", + "doubleSided": false + } + ], + "textures": [ + { + "extensions": { + "KHR_texture_basisu": { + "source": 0 + } + } + } + ], + "images": [ + { + "name": "checkerboard", + "bufferView": 3, + "mimeType": "image/ktx2" + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 72, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 72, + "byteLength": 576, + "byteStride": 12, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 648, + "byteLength": 192, + "byteStride": 8, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 840, + "byteLength": 2647 + } + ], + "buffers": [ + { + "name": "BoxTextured0", + "byteLength": 3488, + "uri": "data:application/octet-stream;base64,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7vP5/u7z+f7u8/n+7vP5/u7z+f7u8/n+fAPn/dE3vvp4+uG3vvp4/PjB5fTxg8tRnMRRnMRRnMRRnMRRnMRRnISIiIiIiIiISCKRSCQSiUQikUgkEomEiIiIiIiIiKiDiYmJiYmJiYmJiYmJiYkJEREREREREZFEIpFIJBKJRCKRSCQSCRERERERERFRBxMTExMTExMTExMTExMTEyIiIiIiIiIiiUQikUgkEolEIpFIJBIiIiIiIiIiog4mJiYmJiYmJiYmJiYmJiZERERERERERBKJRCKRSCQSiUQikUgkREREREREREQdTExMTExMTExMTExMTExMiIiIiIiIiIgkEolEIpFIJBKJRCKRSIiIiIiIiIiIOpiYmJiYmJiYmJiYmJiYmBARERERERERSSQSiUQikUgkEolEIpEQEREREREREXUwMTExMTExMTExMTExMTEhIiIiIiIiIpJIJBKJRCKRSCQSiUQiISIiIiIiIiLqYGJiYmJiYmJiYmJiYmJiQkREREREREQkkUgkEolEIpFIJBKJREJERERERERE1MHExMTExMTExMTExMTExISIiIiIiIiISCKRSCQSiUQikUgkEomEiIiIiIiIiKiDiYmJiYmJiYmJiYmJiYkJEREREREREZFEIpFIJBKJRCKRSCQSCRERERERERFRBxMTExMTExMTExMTExMTEyIiIiIiIiIiiUQikUgkEolEIpFIJBIiIiIiIiIiog4mJiYmJiYmJiYmJiYmJiZERERERERERBKJRCKRSCQSiUQikUgkREREREREREQdTExMTExMTExMTExMTExMiIiIiIiIiIgkEolEIpFIJBKJRCKRSIiIiIiIiIiIOpiYmJiYmJiYmJiYmJiYmBARERERERERSSQSiUQikUgkEolEIpEQEREREREREXUwMTExMTExMTExMTExMTEhIiIiIiIiIpJIJBKJRCKRSCQSiUQiISIiIiIiIiLqYGJiYmJiYmJiYmJiYmJiQkREREREREQkkUgkEolEIpFIJBKJREJEREREREREBAA=" + } + ] +} diff --git a/Specs/Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF-Binary/BoxTexturedKtx2Basis.glb b/Specs/Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF-Binary/BoxTexturedKtx2Basis.glb new file mode 100644 index 000000000000..210b8319826a Binary files /dev/null and b/Specs/Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF-Binary/BoxTexturedKtx2Basis.glb differ diff --git a/Specs/Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF/BoxTexturedKtx2Basis.bin b/Specs/Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF/BoxTexturedKtx2Basis.bin new file mode 100644 index 000000000000..46ac386f3e05 Binary files /dev/null and b/Specs/Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF/BoxTexturedKtx2Basis.bin differ diff --git a/Specs/Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF/BoxTexturedKtx2Basis.gltf b/Specs/Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF/BoxTexturedKtx2Basis.gltf new file mode 100644 index 000000000000..a9a86a1cd652 --- /dev/null +++ b/Specs/Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF/BoxTexturedKtx2Basis.gltf @@ -0,0 +1,200 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "extensionsUsed": [ + "KHR_texture_basisu" + ], + "extensionsRequired": [ + "KHR_texture_basisu" + ], + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1, + 0, + 0, + 0, + 0, + 0, + -1, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 1 + ] + }, + { + "mesh": 0 + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2, + "TEXCOORD_0": 3 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Mesh" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "max": [ + 23 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 1, + 1, + 1 + ], + "min": [ + -1, + -1, + -1 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 288, + "componentType": 5126, + "count": 24, + "max": [ + 0.5, + 0.5, + 0.5 + ], + "min": [ + -0.5, + -0.5, + -0.5 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 6, + 1 + ], + "min": [ + 0, + 0 + ], + "type": "VEC2" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0, + "texCoord": 0 + }, + "metallicFactor": 0, + "baseColorFactor": [ + 1, + 1, + 1, + 1 + ], + "roughnessFactor": 1 + }, + "name": "Texture", + "emissiveFactor": [ + 0, + 0, + 0 + ], + "alphaMode": "OPAQUE", + "doubleSided": false + } + ], + "textures": [ + { + "extensions": { + "KHR_texture_basisu": { + "source": 0 + } + } + } + ], + "images": [ + { + "mimeType": "image/ktx2", + "name": "cesium_logo", + "uri": "cesium_logo.ktx2" + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 72, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 72, + "byteLength": 576, + "byteStride": 12, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 648, + "byteLength": 192, + "byteStride": 8, + "target": 34962 + } + ], + "buffers": [ + { + "name": "BoxTexturedKtx2Basis", + "byteLength": 840, + "uri": "BoxTexturedKtx2Basis.bin" + } + ] +} diff --git a/Specs/Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF/cesium_logo.ktx2 b/Specs/Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF/cesium_logo.ktx2 new file mode 100644 index 000000000000..1c44a7e3925b Binary files /dev/null and b/Specs/Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF/cesium_logo.ktx2 differ diff --git a/Specs/Renderer/TextureSpec.js b/Specs/Renderer/TextureSpec.js index c717c5eebef1..a7dcd2302507 100644 --- a/Specs/Renderer/TextureSpec.js +++ b/Specs/Renderer/TextureSpec.js @@ -1,6 +1,7 @@ import { Cartesian2 } from "../../Source/Cesium.js"; import { Color } from "../../Source/Cesium.js"; -import { loadKTX } from "../../Source/Cesium.js"; +import { loadKTX2 } from "../../Source/Cesium.js"; +import { KTX2Transcoder } from "../../Source/Cesium.js"; import { PixelFormat } from "../../Source/Cesium.js"; import { Resource } from "../../Source/Cesium.js"; import { ClearCommand } from "../../Source/Cesium.js"; @@ -25,9 +26,8 @@ describe( var blueOverRedFlippedImage; var red16x16Image; - var greenDXTImage; - var greenPVRImage; - var greenETC1Image; + var greenKTX2Image; + var greenBasisKTX2Image; var fs = "uniform sampler2D u_texture;" + @@ -85,22 +85,26 @@ describe( red16x16Image = image; }) ); + + var resource = Resource.createIfNeeded("./Data/Images/Green4x4.ktx2"); + var loadPromise = resource.fetchArrayBuffer(); promises.push( - loadKTX("./Data/Images/Green4x4DXT1.ktx").then(function (image) { - greenDXTImage = image; - }) - ); - promises.push( - loadKTX("./Data/Images/Green4x4PVR.ktx").then(function (image) { - greenPVRImage = image; - }) - ); - promises.push( - loadKTX("./Data/Images/Green4x4ETC1.ktx").then(function (image) { - greenETC1Image = image; + loadPromise.then(function (buffer) { + var promise = KTX2Transcoder.transcode(buffer, {}); + return promise.then(function (result) { + greenKTX2Image = result; + }); }) ); + if (context.supportsBasis) { + promises.push( + loadKTX2("./Data/Images/Green4x4_ETC1S.ktx2").then(function (image) { + greenBasisKTX2Image = image; + }) + ); + } + return when.all(promises); }); @@ -432,18 +436,18 @@ describe( } }); - it("draws the expected DXT compressed texture color", function () { - if (!context.s3tc) { + it("draws the expected Basis compressed texture color", function () { + if (!context.supportsBasis) { return; } texture = new Texture({ context: context, - pixelFormat: greenDXTImage.internalFormat, + pixelFormat: greenBasisKTX2Image.internalFormat, source: { - width: greenDXTImage.width, - height: greenDXTImage.height, - arrayBufferView: greenDXTImage.bufferView, + width: greenBasisKTX2Image.width, + height: greenBasisKTX2Image.height, + arrayBufferView: greenBasisKTX2Image.bufferView, }, }); @@ -453,55 +457,31 @@ describe( context: context, fragmentShader: fs, uniformMap: uniformMap, - }).contextToRender([0, 255, 0, 255]); - }); - - it("draws the expected PVR compressed texture color", function () { - if (!context.pvrtc) { - return; - } - - texture = new Texture({ - context: context, - pixelFormat: greenPVRImage.internalFormat, - source: { - width: greenPVRImage.width, - height: greenPVRImage.height, - arrayBufferView: greenPVRImage.bufferView, - }, + }).contextToRenderAndCall(function (color) { + return expect(color).toEqualEpsilon([2, 255, 2, 255], 2); }); - - expect(texture.sizeInBytes).toBe(32); - - expect({ - context: context, - fragmentShader: fs, - uniformMap: uniformMap, - }).contextToRender([0, 255, 0, 255]); }); - it("draws the expected ETC1 compressed texture color", function () { - if (!context.etc1) { - return; - } - + it("draws the expected KTX2 uncompressed texture color", function () { texture = new Texture({ context: context, - pixelFormat: greenETC1Image.internalFormat, + pixelFormat: greenKTX2Image.internalFormat, source: { - width: greenETC1Image.width, - height: greenETC1Image.height, - arrayBufferView: greenETC1Image.bufferView, + width: greenKTX2Image.width, + height: greenKTX2Image.height, + arrayBufferView: greenKTX2Image.bufferView, }, }); - expect(texture.sizeInBytes).toBe(8); + expect(texture.sizeInBytes).toBe(48); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, - }).contextToRender([0, 253, 0, 255]); + }).contextToRenderAndCall(function (color) { + return expect(color).toEqualEpsilon([0, 255, 24, 255], 2); + }); }); it("renders with premultiplied alpha", function () { @@ -1129,70 +1109,6 @@ describe( }).toThrowDeveloperError(); }); - it("throws when creating compressed texture when s3tc is unsupported", function () { - if (!context.s3tc) { - expect(function () { - texture = new Texture({ - context: context, - width: greenDXTImage.width, - height: greenDXTImage.height, - pixelFormat: greenDXTImage.internalFormat, - source: { - arrayBufferView: greenDXTImage.bufferView, - }, - }); - }).toThrowDeveloperError(); - } - }); - - it("throws when creating compressed texture when pvrtc is unsupported", function () { - if (!context.pvrtc) { - expect(function () { - texture = new Texture({ - context: context, - width: greenPVRImage.width, - height: greenPVRImage.height, - pixelFormat: greenPVRImage.internalFormat, - source: { - arrayBufferView: greenPVRImage.bufferView, - }, - }); - }).toThrowDeveloperError(); - } - }); - - it("throws when creating compressed texture when etc1 is unsupported", function () { - if (!context.etc1) { - expect(function () { - texture = new Texture({ - context: context, - width: greenETC1Image.width, - height: greenETC1Image.height, - pixelFormat: greenETC1Image.internalFormat, - source: { - arrayBufferView: greenETC1Image.bufferView, - }, - }); - }).toThrowDeveloperError(); - } - }); - - it("throws when creating compressed texture and the array buffer is not the right length", function () { - if (context.s3tc) { - expect(function () { - texture = new Texture({ - context: context, - width: greenDXTImage.width + 1, - height: greenDXTImage.height, - pixelFormat: greenDXTImage.internalFormat, - source: { - arrayBufferView: greenDXTImage.bufferView, - }, - }); - }).toThrowDeveloperError(); - } - }); - it("throws when creating from the framebuffer with an invalid pixel format", function () { expect(function () { texture = Texture.fromFramebuffer({ @@ -1274,14 +1190,14 @@ describe( }); it("throws when copying to a texture from the framebuffer with a compressed pixel format", function () { - if (context.s3tc) { + if (context.supportsBasis) { texture = new Texture({ context: context, - width: greenDXTImage.width, - height: greenDXTImage.height, - pixelFormat: greenDXTImage.internalFormat, + width: greenBasisKTX2Image.width, + height: greenBasisKTX2Image.height, + pixelFormat: greenBasisKTX2Image.internalFormat, source: { - arrayBufferView: greenDXTImage.bufferView, + arrayBufferView: greenBasisKTX2Image.bufferView, }, }); @@ -1496,14 +1412,14 @@ describe( }); it("throws when copyFrom is given a source with a compressed pixel format", function () { - if (context.s3tc) { + if (context.supportsBasis) { texture = new Texture({ context: context, - width: greenDXTImage.width, - height: greenDXTImage.height, - pixelFormat: greenDXTImage.internalFormat, + width: greenBasisKTX2Image.width, + height: greenBasisKTX2Image.height, + pixelFormat: greenBasisKTX2Image.internalFormat, source: { - arrayBufferView: greenDXTImage.bufferView, + arrayBufferView: greenBasisKTX2Image.bufferView, }, }); @@ -1533,14 +1449,14 @@ describe( }); it("throws when generating mipmaps with a compressed pixel format", function () { - if (context.s3tc) { + if (context.supportsBasis) { texture = new Texture({ context: context, - width: greenDXTImage.width, - height: greenDXTImage.height, - pixelFormat: greenDXTImage.internalFormat, + width: greenBasisKTX2Image.width, + height: greenBasisKTX2Image.height, + pixelFormat: greenBasisKTX2Image.internalFormat, source: { - arrayBufferView: greenDXTImage.bufferView, + arrayBufferView: greenBasisKTX2Image.bufferView, }, }); diff --git a/Specs/Scene/GltfImageLoaderSpec.js b/Specs/Scene/GltfImageLoaderSpec.js index abc0926e693f..4cfab9fade60 100644 --- a/Specs/Scene/GltfImageLoaderSpec.js +++ b/Specs/Scene/GltfImageLoaderSpec.js @@ -1,13 +1,15 @@ import { + BufferLoader, clone, + CompressedTextureBuffer, GltfBufferViewLoader, GltfImageLoader, FeatureDetection, Resource, ResourceCache, - SupportedImageFormats, when, } from "../../Source/Cesium.js"; +import createContext from "../createContext.js"; import dataUriToBuffer from "../dataUriToBuffer.js"; import pollToPromise from "../pollToPromise.js"; @@ -31,6 +33,9 @@ describe("Scene/GltfImageLoader", function () { "data:image/gif;base64,R0lGODdhBAAEAIAAAP///////ywAAAAABAAEAAACBISPCQUAOw==" ); + var ktx2BasisBuffer; + var ktx2BasisMipmapBuffer; + var gltfUri = "https://example.com/model.glb"; var gltfResource = new Resource({ url: gltfUri, @@ -58,9 +63,18 @@ describe("Scene/GltfImageLoader", function () { { uri: "image.png", }, + { + mimeType: "image/ktx2", + bufferView: 0, + }, + { + uri: "image.ktx2", + }, ], }; + var context; + function getGltf(imageBuffer) { var clonedGltf = clone(gltf, true); clonedGltf.buffers[0].byteLength = imageBuffer.byteLength; @@ -68,6 +82,26 @@ describe("Scene/GltfImageLoader", function () { return clonedGltf; } + beforeAll(function () { + context = createContext(); + var ktx2BasisBufferPromise = Resource.fetchArrayBuffer({ + url: "./Data/Images/Green4x4_ETC1S.ktx2", + }).then(function (arrayBuffer) { + ktx2BasisBuffer = new Uint8Array(arrayBuffer); + }); + var ktx2BasisMipmapBufferPromise = Resource.fetchArrayBuffer({ + url: "./Data/Images/Green4x4Mipmap_ETC1S.ktx2", + }).then(function (arrayBuffer) { + ktx2BasisMipmapBuffer = new Uint8Array(arrayBuffer); + }); + + return when.all([ktx2BasisBufferPromise, ktx2BasisMipmapBufferPromise]); + }); + + afterAll(function () { + context.destroyForSpecs(); + }); + afterEach(function () { ResourceCache.clearForSpecs(); }); @@ -80,7 +114,6 @@ describe("Scene/GltfImageLoader", function () { imageId: 0, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); }).toThrowDeveloperError(); }); @@ -93,7 +126,6 @@ describe("Scene/GltfImageLoader", function () { imageId: 0, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); }).toThrowDeveloperError(); }); @@ -106,7 +138,6 @@ describe("Scene/GltfImageLoader", function () { imageId: undefined, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); }).toThrowDeveloperError(); }); @@ -119,7 +150,6 @@ describe("Scene/GltfImageLoader", function () { imageId: 0, gltfResource: undefined, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); }).toThrowDeveloperError(); }); @@ -132,20 +162,6 @@ describe("Scene/GltfImageLoader", function () { imageId: 0, gltfResource: gltfResource, baseResource: undefined, - supportedImageFormats: new SupportedImageFormats(), - }); - }).toThrowDeveloperError(); - }); - - it("throws if supportedImageFormats is undefined", function () { - expect(function () { - return new GltfImageLoader({ - resourceCache: ResourceCache, - gltf: gltf, - imageId: 0, - gltfResource: gltfResource, - baseResource: gltfResource, - supportedImageFormats: undefined, }); }).toThrowDeveloperError(); }); @@ -162,7 +178,6 @@ describe("Scene/GltfImageLoader", function () { imageId: 0, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); imageLoader.load(); @@ -189,7 +204,6 @@ describe("Scene/GltfImageLoader", function () { imageId: 0, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); imageLoader.load(); @@ -215,7 +229,6 @@ describe("Scene/GltfImageLoader", function () { imageId: 1, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); imageLoader.load(); @@ -242,7 +255,6 @@ describe("Scene/GltfImageLoader", function () { imageId: 0, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); imageLoader.load(); @@ -273,6 +285,60 @@ describe("Scene/GltfImageLoader", function () { }); }); + it("loads KTX2/Basis from buffer view", function () { + if (!context.supportsBasis) { + return; + } + + spyOn(BufferLoader, "_fetchArrayBuffer").and.returnValue( + when.resolve(ktx2BasisBuffer) + ); + + var imageLoader = new GltfImageLoader({ + resourceCache: ResourceCache, + gltf: getGltf(ktx2BasisBuffer), + imageId: 2, + gltfResource: gltfResource, + baseResource: gltfResource, + }); + + imageLoader.load(); + + return imageLoader.promise.then(function (imageLoader) { + expect(imageLoader.image instanceof CompressedTextureBuffer).toBe(true); + expect(imageLoader.image.width).toBe(4); + expect(imageLoader.image.height).toBe(4); + expect(imageLoader.mipLevels).toBeUndefined(); + }); + }); + + it("loads KTX2/Basis with mipmap from buffer view", function () { + if (!context.supportsBasis) { + return; + } + + spyOn(BufferLoader, "_fetchArrayBuffer").and.returnValue( + when.resolve(ktx2BasisMipmapBuffer) + ); + + var imageLoader = new GltfImageLoader({ + resourceCache: ResourceCache, + gltf: getGltf(ktx2BasisMipmapBuffer), + imageId: 2, + gltfResource: gltfResource, + baseResource: gltfResource, + }); + + imageLoader.load(); + + return imageLoader.promise.then(function (imageLoader) { + expect(imageLoader.image instanceof CompressedTextureBuffer).toBe(true); + expect(imageLoader.image.width).toBe(4); + expect(imageLoader.image.height).toBe(4); + expect(imageLoader.mipLevels.length).toBe(2); + }); + }); + it("loads from uri", function () { spyOn(Resource.prototype, "fetchImage").and.returnValue( when.resolve(image) @@ -280,11 +346,10 @@ describe("Scene/GltfImageLoader", function () { var imageLoader = new GltfImageLoader({ resourceCache: ResourceCache, - gltf: getGltf(pngBuffer), + gltf: clone(gltf, true), imageId: 1, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); imageLoader.load(); @@ -295,6 +360,36 @@ describe("Scene/GltfImageLoader", function () { }); }); + it("loads KTX2/Basis from uri ", function () { + if (!context.supportsBasis) { + return; + } + + var baseResource = new Resource({ + url: "./Data/Images/", + }); + + var clonedGltf = clone(gltf, true); + clonedGltf.images[3].uri = "Green4x4_ETC1S.ktx2"; + + var imageLoader = new GltfImageLoader({ + resourceCache: ResourceCache, + gltf: clonedGltf, + imageId: 3, + gltfResource: gltfResource, + baseResource: baseResource, + }); + + imageLoader.load(); + + return imageLoader.promise.then(function (imageLoader) { + expect(imageLoader.image instanceof CompressedTextureBuffer).toBe(true); + expect(imageLoader.image.width).toBe(4); + expect(imageLoader.image.height).toBe(4); + expect(imageLoader.mipLevels).toBeUndefined(); + }); + }); + it("destroys image loader", function () { spyOn(Resource.prototype, "fetchArrayBuffer").and.returnValue( when.resolve(pngBuffer) @@ -311,7 +406,6 @@ describe("Scene/GltfImageLoader", function () { imageId: 0, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); expect(imageLoader.image).not.toBeDefined(); @@ -350,7 +444,6 @@ describe("Scene/GltfImageLoader", function () { imageId: 0, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); expect(imageLoader.image).not.toBeDefined(); @@ -403,7 +496,6 @@ describe("Scene/GltfImageLoader", function () { imageId: 0, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); expect(imageLoader.image).not.toBeDefined(); @@ -443,7 +535,6 @@ describe("Scene/GltfImageLoader", function () { imageId: 1, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); expect(imageLoader.image).not.toBeDefined(); diff --git a/Specs/Scene/GltfLoaderSpec.js b/Specs/Scene/GltfLoaderSpec.js index 5f5fdaa2fee6..bdb8ac879271 100644 --- a/Specs/Scene/GltfLoaderSpec.js +++ b/Specs/Scene/GltfLoaderSpec.js @@ -44,6 +44,10 @@ describe( "./Data/Models/GltfLoader/BoxTextured/glTF-Binary/BoxTextured.glb"; var boxTexturedEmbedded = "./Data/Models/GltfLoader/BoxTextured/glTF-Embedded/BoxTextured.gltf"; + var boxTexturedKtx2Basis = + "./Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF/BoxTexturedKtx2Basis.gltf"; + var boxTexturedKtx2BasisBinary = + "./Data/Models/GltfLoader/BoxTexturedKtx2Basis/glTF-Binary/BoxTexturedKtx2Basis.glb"; var boxVertexColors = "./Data/Models/GltfLoader/BoxVertexColors/glTF/BoxVertexColors.gltf"; var simpleMorph = @@ -359,6 +363,47 @@ describe( ); }); + function loadsBoxTexturedKtx2Basis(gltfPath) { + return loadGltf(gltfPath).then(function (gltfLoader) { + var components = gltfLoader.components; + var scene = components.scene; + var rootNode = scene.nodes[0]; + var childNode = rootNode.children[0]; + var primitive = childNode.primitives[0]; + var material = primitive.material; + var metallicRoughness = material.metallicRoughness; + + var texture = metallicRoughness.baseColorTexture.texture; + var sampler = texture.sampler; + + expect(texture.width).toBe(256); + expect(texture.height).toBe(256); + + expect(sampler.wrapS).toBe(TextureWrap.REPEAT); + expect(sampler.wrapT).toBe(TextureWrap.REPEAT); + expect(sampler.magnificationFilter).toBe( + TextureMagnificationFilter.LINEAR + ); + expect(sampler.minificationFilter).toBe( + TextureMinificationFilter.LINEAR + ); + }); + } + + it("loads BoxTexturedKtx2Basis", function () { + if (!scene.context.supportsBasis) { + return; + } + return loadsBoxTexturedKtx2Basis(boxTexturedKtx2Basis); + }); + + it("loads BoxTexturedKtx2BasisBinary", function () { + if (!scene.context.supportsBasis) { + return; + } + return loadsBoxTexturedKtx2Basis(boxTexturedKtx2BasisBinary); + }); + it("loads BoxVertexColors", function () { return loadGltf(boxVertexColors).then(function (gltfLoader) { var components = gltfLoader.components; diff --git a/Specs/Scene/GltfLoaderUtilSpec.js b/Specs/Scene/GltfLoaderUtilSpec.js index bbaf98393f3c..33f2b55963e8 100644 --- a/Specs/Scene/GltfLoaderUtilSpec.js +++ b/Specs/Scene/GltfLoaderUtilSpec.js @@ -24,6 +24,9 @@ describe("Scene/GltfLoaderUtil", function () { { uri: "image.webp", }, + { + uri: "image.ktx2", + }, ], textures: [ { @@ -37,6 +40,14 @@ describe("Scene/GltfLoaderUtil", function () { }, }, }, + { + source: 0, + extensions: { + KHR_texture_basisu: { + source: 3, + }, + }, + }, ], }; @@ -101,6 +112,28 @@ describe("Scene/GltfLoaderUtil", function () { expect(imageId).toBe(0); }); + it("getImageIdFromTexture gets KTX2 image when KHR_texture_basisu extension is supported", function () { + var imageId = GltfLoaderUtil.getImageIdFromTexture({ + gltf: gltfWithTextures, + textureId: 2, + supportedImageFormats: new SupportedImageFormats({ + basis: true, + }), + }); + expect(imageId).toBe(3); + }); + + it("getImageIdFromTexture gets default image when KHR_texture_basisu extension is not supported", function () { + var imageId = GltfLoaderUtil.getImageIdFromTexture({ + gltf: gltfWithTextures, + textureId: 2, + supportedImageFormats: new SupportedImageFormats({ + basis: false, + }), + }); + expect(imageId).toBe(0); + }); + it("createSampler throws if gltf is undefined", function () { expect(function () { GltfLoaderUtil.getImageIdFromTexture({ @@ -112,7 +145,7 @@ describe("Scene/GltfLoaderUtil", function () { }).toThrowDeveloperError(); }); - it("createSampler throws if gltf is undefined", function () { + it("createSampler throws if textureInfo is undefined", function () { expect(function () { GltfLoaderUtil.getImageIdFromTexture({ gltf: gltfWithTextures, @@ -140,6 +173,64 @@ describe("Scene/GltfLoaderUtil", function () { expect(sampler.magnificationFilter).toBe(TextureMagnificationFilter.LINEAR); }); + it("createSampler uses NEAREST when compressedTextureNoMipmap is true and the minFilter uses nearest mipmap filtering", function () { + var sampler = GltfLoaderUtil.createSampler({ + gltf: { + textures: [ + { + source: 0, + sampler: 0, + }, + ], + samplers: [ + { + magFilter: 9729, + minFilter: 9986, + wrapS: 10497, + wrapT: 10497, + }, + ], + }, + textureInfo: { + index: 0, + }, + compressedTextureNoMipmap: true, + }); + expect(sampler.wrapS).toBe(TextureWrap.REPEAT); + expect(sampler.wrapT).toBe(TextureWrap.REPEAT); + expect(sampler.minificationFilter).toBe(TextureMinificationFilter.NEAREST); + expect(sampler.magnificationFilter).toBe(TextureMagnificationFilter.LINEAR); + }); + + it("createSampler uses LINEAR when compressedTextureNoMipmap is true and the minFilter uses linear mipmap filtering", function () { + var sampler = GltfLoaderUtil.createSampler({ + gltf: { + textures: [ + { + source: 0, + sampler: 0, + }, + ], + samplers: [ + { + magFilter: 9729, + minFilter: 9987, + wrapS: 10497, + wrapT: 10497, + }, + ], + }, + textureInfo: { + index: 0, + }, + compressedTextureNoMipmap: true, + }); + expect(sampler.wrapS).toBe(TextureWrap.REPEAT); + expect(sampler.wrapT).toBe(TextureWrap.REPEAT); + expect(sampler.minificationFilter).toBe(TextureMinificationFilter.LINEAR); + expect(sampler.magnificationFilter).toBe(TextureMagnificationFilter.LINEAR); + }); + function createSampler(options) { var gltf = { textures: [ diff --git a/Specs/Scene/GltfTextureLoaderSpec.js b/Specs/Scene/GltfTextureLoaderSpec.js index 04301cc8d977..faefc3d80eda 100644 --- a/Specs/Scene/GltfTextureLoaderSpec.js +++ b/Specs/Scene/GltfTextureLoaderSpec.js @@ -1,11 +1,14 @@ import { + clone, GltfImageLoader, GltfTextureLoader, + GltfLoaderUtil, JobScheduler, Resource, ResourceCache, SupportedImageFormats, Texture, + TextureMinificationFilter, when, } from "../../Source/Cesium.js"; import createScene from "../createScene.js"; @@ -75,6 +78,68 @@ describe( ], }; + var gltfKtx2BaseResource = new Resource({ + url: "./Data/Images/", + }); + + var gltfKtx2 = { + images: [ + { + uri: "image.png", + }, + { + uri: "Green4x4_ETC1S.ktx2", + }, + { + uri: "Green4x4Mipmap_ETC1S.ktx2", + }, + ], + textures: [ + { + source: 0, + sampler: 0, + extensions: { + KHR_texture_basisu: { + source: 1, + }, + }, + }, + { + source: 0, + sampler: 1, + extensions: { + KHR_texture_basisu: { + source: 2, + }, + }, + }, + ], + materials: [ + { + emissiveTexture: { + index: 0, + }, + occlusionTexture: { + index: 1, + }, + }, + ], + samplers: [ + { + magFilter: 9728, // NEAREST + minFilter: 9728, // NEAREST + wrapS: 10497, // REPEAT + wrapT: 10497, // REPEAT + }, + { + magFilter: 9728, // NEAREST + minFilter: 9984, // NEAREST_MIPMAP_NEAREST + wrapS: 33071, // CLAMP_TO_EDGE + wrapT: 33071, // CLAMP_TO_EDGE + }, + ], + }; + var scene; beforeAll(function () { @@ -263,6 +328,105 @@ describe( }); }); + it("loads KTX2/Basis texture", function () { + if (!scene.context.supportsBasis) { + return; + } + + var gl = scene.context._gl; + spyOn(gl, "compressedTexImage2D").and.callThrough(); + + var textureLoader = new GltfTextureLoader({ + resourceCache: ResourceCache, + gltf: gltfKtx2, + textureInfo: gltf.materials[0].emissiveTexture, + gltfResource: gltfResource, + baseResource: gltfKtx2BaseResource, + supportedImageFormats: new SupportedImageFormats({ + basis: true, + }), + }); + + textureLoader.load(); + + return waitForLoaderProcess(textureLoader, scene).then(function ( + textureLoader + ) { + expect(textureLoader.texture.width).toBe(4); + expect(textureLoader.texture.height).toBe(4); + expect(gl.compressedTexImage2D.calls.count()).toEqual(1); + }); + }); + + it("loads KTX2/Basis texture with mipmap", function () { + if (!scene.context.supportsBasis) { + return; + } + + var gl = scene.context._gl; + spyOn(gl, "compressedTexImage2D").and.callThrough(); + + var textureLoader = new GltfTextureLoader({ + resourceCache: ResourceCache, + gltf: gltfKtx2, + textureInfo: gltf.materials[0].occlusionTexture, + gltfResource: gltfResource, + baseResource: gltfKtx2BaseResource, + supportedImageFormats: new SupportedImageFormats({ + basis: true, + }), + }); + + textureLoader.load(); + + return waitForLoaderProcess(textureLoader, scene).then(function ( + textureLoader + ) { + expect(textureLoader.texture.width).toBe(4); + expect(textureLoader.texture.height).toBe(4); + expect(gl.compressedTexImage2D.calls.count()).toEqual(3); + }); + }); + + it("loads KTX2/Basis texture with incompatible mipmap sampler", function () { + if (!scene.context.supportsBasis) { + return; + } + + spyOn(GltfLoaderUtil, "createSampler").and.callThrough(); + + var gltfKtx2MissingMipmap = clone(gltfKtx2, true); + gltfKtx2MissingMipmap.samplers[0].minFilter = + TextureMinificationFilter.NEAREST_MIPMAP_NEAREST; + + var textureLoader = new GltfTextureLoader({ + resourceCache: ResourceCache, + gltf: gltfKtx2MissingMipmap, + textureInfo: gltfKtx2MissingMipmap.materials[0].emissiveTexture, + gltfResource: gltfResource, + baseResource: gltfKtx2BaseResource, + supportedImageFormats: new SupportedImageFormats({ + basis: true, + }), + asynchronous: false, + }); + + textureLoader.load(); + + return waitForLoaderProcess(textureLoader, scene).then(function ( + textureLoader + ) { + expect(GltfLoaderUtil.createSampler).toHaveBeenCalledWith({ + gltf: gltfKtx2MissingMipmap, + textureInfo: gltf.materials[0].emissiveTexture, + compressedTextureNoMipmap: true, + }); + expect(textureLoader.texture.sampler.minificationFilter).toBe( + TextureMinificationFilter.NEAREST + ); + }); + }); + it("generates mipmap if sampler requires it", function () { spyOn(Resource.prototype, "fetchImage").and.returnValue( when.resolve(image) @@ -397,7 +561,6 @@ describe( imageId: 0, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); var textureLoader = new GltfTextureLoader({ diff --git a/Specs/Scene/MaterialSpec.js b/Specs/Scene/MaterialSpec.js index 5ac0984a7d3b..63abff825c82 100644 --- a/Specs/Scene/MaterialSpec.js +++ b/Specs/Scene/MaterialSpec.js @@ -10,6 +10,7 @@ import { Resource } from "../../Source/Cesium.js"; import { Material } from "../../Source/Cesium.js"; import { MaterialAppearance } from "../../Source/Cesium.js"; import { PolylineCollection } from "../../Source/Cesium.js"; +import { FeatureDetection } from "../../Source/Cesium.js"; import { Primitive } from "../../Source/Cesium.js"; import { TextureMagnificationFilter } from "../../Source/Cesium.js"; import { TextureMinificationFilter } from "../../Source/Cesium.js"; @@ -367,15 +368,10 @@ describe( renderMaterial(material); }); - it("creates a material with an ktx compressed image uniform", function () { + it("creates a material with an KTX2 compressed image uniform", function () { var compressedUrl; - var context = scene.context; - if (context.s3tc) { - compressedUrl = "./Data/Images/Green4x4DXT1.ktx"; - } else if (context.etc1) { - compressedUrl = "./Data/Images/Green4x4ETC1.ktx"; - } else if (context.pvrtc) { - compressedUrl = "./Data/Images/Green4x4PVR.ktx"; + if (FeatureDetection.supportsBasis(scene)) { + compressedUrl = "./Data/Images/Green4x4.ktx2"; } else { return; } @@ -392,25 +388,6 @@ describe( renderMaterial(material); }); - it("creates a material with an crn compressed image uniform", function () { - var context = scene.context; - if (!context.s3tc) { - return; - } - - var compressedUrl = "./Data/Images/Green4x4.crn"; - var material = new Material({ - strict: true, - fabric: { - type: "DiffuseMap", - uniforms: { - image: compressedUrl, - }, - }, - }); - renderMaterial(material); - }); - it("creates a material with a cube map uniform", function () { var material = new Material({ strict: true, diff --git a/Specs/Scene/ModelSpec.js b/Specs/Scene/ModelSpec.js index bd014fbf47eb..89406a71f3df 100644 --- a/Specs/Scene/ModelSpec.js +++ b/Specs/Scene/ModelSpec.js @@ -50,18 +50,10 @@ describe( "./Data/Models/Box-Textured-Separate/CesiumTexturedBoxTest.gltf"; var texturedBoxBasePathUrl = "./Data/Models/Box-Textured-BasePath/CesiumTexturedBoxTest.gltf"; - var texturedBoxKTXUrl = - "./Data/Models/Box-Textured-KTX/CesiumTexturedBoxTest.gltf"; - var texturedBoxKTXBinaryUrl = - "./Data/Models/Box-Textured-KTX-Binary/CesiumTexturedBoxTest.glb"; - var texturedBoxKTXEmbeddedUrl = - "./Data/Models/Box-Textured-KTX-Embedded/CesiumTexturedBoxTest.gltf"; - var texturedBoxCRNUrl = - "./Data/Models/Box-Textured-CRN/CesiumTexturedBoxTest.gltf"; - var texturedBoxCRNBinaryUrl = - "./Data/Models/Box-Textured-CRN-Binary/CesiumTexturedBoxTest.glb"; - var texturedBoxCRNEmbeddedUrl = - "./Data/Models/Box-Textured-CRN-Embedded/CesiumTexturedBoxTest.gltf"; + var texturedBoxKTX2Url = + "./Data/Models/Box-Textured-KTX2-Basis/CesiumTexturedBoxTest.gltf"; + var texturedBoxKTX2MipmapUrl = + "./Data/Models/Box-Textured-KTX2-Mipmap/CheckerboardTexturedBoxTest.gltf"; var texturedBoxCustomUrl = "./Data/Models/Box-Textured-Custom/CesiumTexturedBoxTest.gltf"; var texturedBoxKhrBinaryUrl = @@ -807,7 +799,7 @@ describe( return loadModel(boomBoxUrl).then(function (m) { m.scale = 20.0; // Source model is very small, so scale up a bit m.specularEnvironmentMaps = - "./Data/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx"; + "./Data/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx2"; return pollToPromise(function () { scene.highDynamicRange = true; @@ -1380,54 +1372,11 @@ describe( }); }); - it("renders textured box with external KTX texture", function () { - return loadModel(texturedBoxKTXUrl, { - incrementallyLoadTextures: false, - }).then(function (m) { - verifyRender(m); - expect(Object.keys(m._rendererResources.textures).length).toBe(1); - primitives.remove(m); - }); - }); - - it("renders textured box with embedded binary KTX texture", function () { - return loadModel(texturedBoxKTXBinaryUrl, { - incrementallyLoadTextures: false, - }).then(function (m) { - verifyRender(m); - expect(Object.keys(m._rendererResources.textures).length).toBe(1); - primitives.remove(m); - }); - }); - - it("renders textured box with embedded base64 encoded KTX texture", function () { - return loadModel(texturedBoxKTXEmbeddedUrl, { - incrementallyLoadTextures: false, - }).then(function (m) { - verifyRender(m); - expect(Object.keys(m._rendererResources.textures).length).toBe(1); - primitives.remove(m); - }); - }); - - it("renders textured box with external CRN texture", function () { - if (!scene.context.s3tc) { - return; - } - return loadModel(texturedBoxCRNUrl, { - incrementallyLoadTextures: false, - }).then(function (m) { - verifyRender(m); - expect(Object.keys(m._rendererResources.textures).length).toBe(1); - primitives.remove(m); - }); - }); - - it("renders textured box with embedded binary CRN texture", function () { - if (!scene.context.s3tc) { + it("renders textured box with embedded KTX2 texture", function () { + if (!scene.context.supportsBasis) { return; } - return loadModel(texturedBoxCRNBinaryUrl, { + return loadModel(texturedBoxKTX2Url, { incrementallyLoadTextures: false, }).then(function (m) { verifyRender(m); @@ -1436,14 +1385,17 @@ describe( }); }); - it("renders textured box with embedded base64 encoded CRN texture", function () { - if (!scene.context.s3tc) { + it("renders textured box with embedded KTX2 texture with mipmap", function () { + if (!scene.context.supportsBasis) { return; } - return loadModel(texturedBoxCRNEmbeddedUrl, { + var gl = scene.context._gl; + spyOn(gl, "compressedTexImage2D").and.callThrough(); + return loadModel(texturedBoxKTX2MipmapUrl, { incrementallyLoadTextures: false, }).then(function (m) { verifyRender(m); + expect(gl.compressedTexImage2D.calls.count()).toEqual(9); expect(Object.keys(m._rendererResources.textures).length).toBe(1); primitives.remove(m); }); diff --git a/Specs/Scene/OctahedralProjectedCubeMapSpec.js b/Specs/Scene/OctahedralProjectedCubeMapSpec.js index 95a2c6fb4a95..98173ce414da 100644 --- a/Specs/Scene/OctahedralProjectedCubeMapSpec.js +++ b/Specs/Scene/OctahedralProjectedCubeMapSpec.js @@ -14,7 +14,7 @@ describe( var octahedralMap; var environmentMapUrl = - "./Data/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx"; + "./Data/EnvironmentMap/kiara_6_afternoon_2k_ibl.ktx2"; var fsOctahedralMap = "uniform sampler2D projectedMap;" + "uniform vec2 textureSize;" + @@ -30,10 +30,8 @@ describe( "uniform samplerCube cubeMap;" + "uniform vec3 direction;" + "void main() {" + - " vec4 rgbm = textureCube(cubeMap, direction);" + - " float m = rgbm.a * 16.0;" + - " vec3 r = rgbm.rgb * m;" + - " gl_FragColor = vec4(r * r, 1.0);" + + " vec4 rgba = textureCube(cubeMap, direction);" + + " gl_FragColor = vec4(rgba.rgb, 1.0);" + "}"; beforeAll(function () { @@ -113,7 +111,7 @@ describe( sampleOctahedralMap(octahedralMap, directionFlipY, lod, function ( octahedralMapColor ) { - return expect(cubeMapColor).toEqualEpsilon(octahedralMapColor, 5); + return expect(cubeMapColor).toEqualEpsilon(octahedralMapColor, 6); }); }); } diff --git a/Specs/Scene/ResourceCacheKeySpec.js b/Specs/Scene/ResourceCacheKeySpec.js index d32370dde8d2..19ff0a4009a9 100644 --- a/Specs/Scene/ResourceCacheKeySpec.js +++ b/Specs/Scene/ResourceCacheKeySpec.js @@ -197,6 +197,9 @@ describe("ResourceCacheKey", function () { { uri: "image.webp", }, + { + uri: "image.ktx2", + }, ], textures: [ { @@ -215,6 +218,14 @@ describe("ResourceCacheKey", function () { }, }, }, + { + source: 0, + extensions: { + KHR_texture_basisu: { + source: 3, + }, + }, + }, ], samplers: [ { @@ -622,7 +633,6 @@ describe("ResourceCacheKey", function () { imageId: 0, gltfResource: gltfResource, baseResource: baseResource, - supportedImageFormats: new SupportedImageFormats(), }); expect(cacheKey).toBe("image:https://example.com/resources/image.png"); @@ -634,7 +644,6 @@ describe("ResourceCacheKey", function () { imageId: 1, gltfResource: gltfResource, baseResource: baseResource, - supportedImageFormats: new SupportedImageFormats(), }); expect(cacheKey).toBe( @@ -649,7 +658,6 @@ describe("ResourceCacheKey", function () { imageId: 0, gltfResource: gltfResource, baseResource: baseResource, - supportedImageFormats: new SupportedImageFormats(), }); }).toThrowDeveloperError(); }); @@ -661,7 +669,6 @@ describe("ResourceCacheKey", function () { imageId: undefined, gltfResource: gltfResource, baseResource: baseResource, - supportedImageFormats: new SupportedImageFormats(), }); }).toThrowDeveloperError(); }); @@ -673,7 +680,6 @@ describe("ResourceCacheKey", function () { imageId: 0, gltfResource: undefined, baseResource: baseResource, - supportedImageFormats: new SupportedImageFormats(), }); }).toThrowDeveloperError(); }); @@ -685,19 +691,6 @@ describe("ResourceCacheKey", function () { imageId: 0, gltfResource: gltfResource, baseResource: undefined, - supportedImageFormats: new SupportedImageFormats(), - }); - }).toThrowDeveloperError(); - }); - - it("getImageCacheKey throws if supportedImageFormats is undefined", function () { - expect(function () { - ResourceCacheKey.getImageCacheKey({ - gltf: gltfWithTextures, - imageId: 0, - gltfResource: gltfResource, - baseResource: baseResource, - supportedImageFormats: undefined, }); }).toThrowDeveloperError(); }); @@ -772,6 +765,42 @@ describe("ResourceCacheKey", function () { ); }); + it("getTextureCacheKey works with KHR_texture_basisu extension", function () { + var cacheKey = ResourceCacheKey.getTextureCacheKey({ + gltf: gltfWithTextures, + textureInfo: { + index: 3, + texCoord: 0, + }, + gltfResource: gltfResource, + baseResource: baseResource, + supportedImageFormats: new SupportedImageFormats({ + basis: true, + }), + }); + + expect(cacheKey).toBe( + "texture:https://example.com/resources/image.ktx2-sampler-10497-10497-9729-9729" + ); + }); + + it("getTextureCacheKey ignores KHR_texture_basisu extension if Basis is not supported", function () { + var cacheKey = ResourceCacheKey.getTextureCacheKey({ + gltf: gltfWithTextures, + textureInfo: { + index: 3, + texCoord: 0, + }, + gltfResource: gltfResource, + baseResource: baseResource, + supportedImageFormats: new SupportedImageFormats(), + }); + + expect(cacheKey).toBe( + "texture:https://example.com/resources/image.png-sampler-10497-10497-9729-9729" + ); + }); + it("getTextureCacheKey throws if gltf is undefined", function () { expect(function () { ResourceCacheKey.getTextureCacheKey({ diff --git a/Specs/Scene/ResourceCacheSpec.js b/Specs/Scene/ResourceCacheSpec.js index 45d627a88124..4df03602319d 100644 --- a/Specs/Scene/ResourceCacheSpec.js +++ b/Specs/Scene/ResourceCacheSpec.js @@ -1150,14 +1150,12 @@ describe( imageId: 0, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); var imageLoader = ResourceCache.loadImage({ gltf: gltfWithTextures, imageId: 0, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); var cacheEntry = ResourceCache.cacheEntries[expectedCacheKey]; expect(imageLoader.cacheKey).toBe(expectedCacheKey); @@ -1170,7 +1168,6 @@ describe( imageId: 0, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }) ).toBe(imageLoader); @@ -1183,60 +1180,44 @@ describe( it("loadImage throws if gltf is undefined", function () { expect(function () { - ResourceCache.loadIndexBuffer({ + ResourceCache.loadImage({ gltf: undefined, imageId: 0, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); }).toThrowDeveloperError(); }); it("loadImage throws if imageId is undefined", function () { expect(function () { - ResourceCache.loadIndexBuffer({ + ResourceCache.loadImage({ gltf: gltfWithTextures, imageId: undefined, gltfResource: gltfResource, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); }).toThrowDeveloperError(); }); it("loadImage throws if gltfResource is undefined", function () { expect(function () { - ResourceCache.loadIndexBuffer({ + ResourceCache.loadImage({ gltf: gltfWithTextures, imageId: 0, gltfResource: undefined, baseResource: gltfResource, - supportedImageFormats: new SupportedImageFormats(), }); }).toThrowDeveloperError(); }); it("loadImage throws if baseResource is undefined", function () { expect(function () { - ResourceCache.loadIndexBuffer({ + ResourceCache.loadImage({ gltf: gltfWithTextures, imageId: 0, gltfResource: gltfResource, baseResource: undefined, - supportedImageFormats: new SupportedImageFormats(), - }); - }).toThrowDeveloperError(); - }); - - it("loadImage throws if supportedImageFormats is undefined", function () { - expect(function () { - ResourceCache.loadIndexBuffer({ - gltf: gltfWithTextures, - imageId: 0, - gltfResource: gltfResource, - baseResource: gltfResource, - supportedImageFormats: undefined, }); }).toThrowDeveloperError(); }); @@ -1286,7 +1267,7 @@ describe( it("loadTexture throws if gltf is undefined", function () { expect(function () { - ResourceCache.loadIndexBuffer({ + ResourceCache.loadTexture({ gltf: undefined, textureInfo: gltfWithTextures.materials[0].emissiveTexture, gltfResource: gltfResource, @@ -1298,7 +1279,7 @@ describe( it("loadTexture throws if textureInfo is undefined", function () { expect(function () { - ResourceCache.loadIndexBuffer({ + ResourceCache.loadTexture({ gltf: gltfWithTextures, textureInfo: undefined, gltfResource: gltfResource, @@ -1310,7 +1291,7 @@ describe( it("loadTexture throws if gltfResource is undefined", function () { expect(function () { - ResourceCache.loadIndexBuffer({ + ResourceCache.loadTexture({ gltf: gltfWithTextures, textureInfo: gltfWithTextures.materials[0].emissiveTexture, gltfResource: undefined, @@ -1322,7 +1303,7 @@ describe( it("loadTexture throws if baseResource is undefined", function () { expect(function () { - ResourceCache.loadIndexBuffer({ + ResourceCache.loadTexture({ gltf: gltfWithTextures, textureInfo: gltfWithTextures.materials[0].emissiveTexture, gltfResource: gltfResource, @@ -1334,7 +1315,7 @@ describe( it("loadTexture throws if supportedImageFormats is undefined", function () { expect(function () { - ResourceCache.loadIndexBuffer({ + ResourceCache.loadTexture({ gltf: gltfWithTextures, textureInfo: gltfWithTextures.materials[0].emissiveTexture, gltfResource: gltfResource, diff --git a/Specs/Scene/SupportedImageFormatsSpec.js b/Specs/Scene/SupportedImageFormatsSpec.js index a558e201a937..3f9c75469917 100644 --- a/Specs/Scene/SupportedImageFormatsSpec.js +++ b/Specs/Scene/SupportedImageFormatsSpec.js @@ -4,21 +4,15 @@ describe("Scene/SupportedImageFormats", function () { it("constructs with options", function () { var supportedImageFormats = new SupportedImageFormats({ webp: true, - s3tc: false, - pvrtc: true, - etc1: false, + basis: false, }); expect(supportedImageFormats.webp).toBe(true); - expect(supportedImageFormats.s3tc).toBe(false); - expect(supportedImageFormats.pvrtc).toBe(true); - expect(supportedImageFormats.etc1).toBe(false); + expect(supportedImageFormats.basis).toBe(false); }); it("constructs with default values", function () { var supportedImageFormats = new SupportedImageFormats({}); expect(supportedImageFormats.webp).toBe(false); - expect(supportedImageFormats.s3tc).toBe(false); - expect(supportedImageFormats.pvrtc).toBe(false); - expect(supportedImageFormats.etc1).toBe(false); + expect(supportedImageFormats.basis).toBe(false); }); }); diff --git a/gulpfile.cjs b/gulpfile.cjs index 3c265ef865b7..7377604408fc 100644 --- a/gulpfile.cjs +++ b/gulpfile.cjs @@ -74,7 +74,6 @@ const sourceFiles = [ "!Source/ThirdParty/Workers/**", "!Source/ThirdParty/google-earth-dbroot-parser.js", "!Source/ThirdParty/pako_inflate.js", - "!Source/ThirdParty/crunch.js", ]; const watchedFiles = [ @@ -126,7 +125,7 @@ function rollupWarning(message) { // Ignore eval warnings in third-party code we don't have control over if ( message.code === "EVAL" && - /(protobuf-minimal|crunch)\.js$/.test(message.loc.file) + /protobuf-minimal\.js$/.test(message.loc.file) ) { return; } @@ -737,7 +736,7 @@ function getMimeType(filename) { return { type: "text/plain", compress: true }; } else if (/\.(czml|topojson)$/i.test(filename)) { return { type: "application/json", compress: true }; - } else if (/\.(crn|tgz)$/i.test(filename)) { + } else if (/\.tgz$/i.test(filename)) { return { type: "application/octet-stream", compress: false }; } diff --git a/server.cjs b/server.cjs index 2ded8466d84f..1b0623c0b6ab 100644 --- a/server.cjs +++ b/server.cjs @@ -48,8 +48,7 @@ { "application/json": ["czml", "json", "geojson", "topojson"], "application/wasm": ["wasm"], - "image/crn": ["crn"], - "image/ktx": ["ktx"], + "image/ktx2": ["ktx2"], "model/gltf+json": ["gltf"], "model/gltf-binary": ["bgltf", "glb"], "application/octet-stream": [ diff --git a/web.config b/web.config index 9330dbc8efce..29f8221b1420 100644 --- a/web.config +++ b/web.config @@ -40,10 +40,8 @@ - - - - + +