123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492 |
- import Check from "../Core/Check.js";
- import defaultValue from "../Core/defaultValue.js";
- import defer from "../Core/defer.js";
- import defined from "../Core/defined.js";
- import DeveloperError from "../Core/DeveloperError.js";
- import parseStructuralMetadata from "./parseStructuralMetadata.js";
- import parseFeatureMetadataLegacy from "./parseFeatureMetadataLegacy.js";
- import ResourceCache from "./ResourceCache.js";
- import ResourceLoader from "./ResourceLoader.js";
- import ResourceLoaderState from "./ResourceLoaderState.js";
- /**
- * Loads glTF structural metadata
- * <p>
- * Implements the {@link ResourceLoader} interface.
- * </p>
- *
- * @alias GltfStructuralMetadataLoader
- * @constructor
- * @augments ResourceLoader
- *
- * @param {Object} options Object with the following properties:
- * @param {Object} options.gltf The glTF JSON.
- * @param {String} [options.extension] The <code>EXT_structural_metadata</code> extension object. If this is undefined, then extensionLegacy must be defined.
- * @param {String} [options.extensionLegacy] The legacy <code>EXT_feature_metadata</code> extension for backwards compatibility.
- * @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.
- * @param {Boolean} [options.asynchronous=true] Determines if WebGL resource creation will be spread out over several frames or block until all WebGL resources are created.
- *
- * @private
- * @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
- */
- export default function GltfStructuralMetadataLoader(options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- const gltf = options.gltf;
- const extension = options.extension;
- const extensionLegacy = options.extensionLegacy;
- const gltfResource = options.gltfResource;
- const baseResource = options.baseResource;
- const supportedImageFormats = options.supportedImageFormats;
- const cacheKey = options.cacheKey;
- const asynchronous = defaultValue(options.asynchronous, true);
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options.gltf", gltf);
- Check.typeOf.object("options.gltfResource", gltfResource);
- Check.typeOf.object("options.baseResource", baseResource);
- Check.typeOf.object("options.supportedImageFormats", supportedImageFormats);
- if (!defined(options.extension) && !defined(options.extensionLegacy)) {
- throw new DeveloperError(
- "One of options.extension or options.extensionLegacy must be specified"
- );
- }
- //>>includeEnd('debug');
- this._gltfResource = gltfResource;
- this._baseResource = baseResource;
- this._gltf = gltf;
- this._extension = extension;
- this._extensionLegacy = extensionLegacy;
- this._supportedImageFormats = supportedImageFormats;
- this._cacheKey = cacheKey;
- this._asynchronous = asynchronous;
- this._bufferViewLoaders = [];
- this._textureLoaders = [];
- this._schemaLoader = undefined;
- this._structuralMetadata = undefined;
- this._state = ResourceLoaderState.UNLOADED;
- this._promise = defer();
- }
- if (defined(Object.create)) {
- GltfStructuralMetadataLoader.prototype = Object.create(
- ResourceLoader.prototype
- );
- GltfStructuralMetadataLoader.prototype.constructor = GltfStructuralMetadataLoader;
- }
- Object.defineProperties(GltfStructuralMetadataLoader.prototype, {
- /**
- * A promise that resolves to the resource when the resource is ready.
- *
- * @memberof GltfStructuralMetadataLoader.prototype
- *
- * @type {Promise.<GltfStructuralMetadataLoader>}
- * @readonly
- * @private
- */
- promise: {
- get: function () {
- return this._promise.promise;
- },
- },
- /**
- * The cache key of the resource.
- *
- * @memberof GltfStructuralMetadataLoader.prototype
- *
- * @type {String}
- * @readonly
- * @private
- */
- cacheKey: {
- get: function () {
- return this._cacheKey;
- },
- },
- /**
- * The parsed structural metadata
- *
- * @memberof GltfStructuralMetadataLoader.prototype
- *
- * @type {StructuralMetadata}
- * @readonly
- * @private
- */
- structuralMetadata: {
- get: function () {
- return this._structuralMetadata;
- },
- },
- });
- /**
- * Loads the resource.
- * @private
- */
- GltfStructuralMetadataLoader.prototype.load = function () {
- const bufferViewsPromise = loadBufferViews(this);
- const texturesPromise = loadTextures(this);
- const schemaPromise = loadSchema(this);
- this._gltf = undefined; // No longer need to hold onto the glTF
- this._state = ResourceLoaderState.LOADING;
- const that = this;
- Promise.all([bufferViewsPromise, texturesPromise, schemaPromise])
- .then(function (results) {
- if (that.isDestroyed()) {
- return;
- }
- const bufferViews = results[0];
- const textures = results[1];
- const schema = results[2];
- if (defined(that._extension)) {
- that._structuralMetadata = parseStructuralMetadata({
- extension: that._extension,
- schema: schema,
- bufferViews: bufferViews,
- textures: textures,
- });
- } else {
- that._structuralMetadata = parseFeatureMetadataLegacy({
- extension: that._extensionLegacy,
- schema: schema,
- bufferViews: bufferViews,
- textures: textures,
- });
- }
- that._state = ResourceLoaderState.READY;
- that._promise.resolve(that);
- })
- .catch(function (error) {
- if (that.isDestroyed()) {
- return;
- }
- that.unload();
- that._state = ResourceLoaderState.FAILED;
- const errorMessage = "Failed to load structural metadata";
- that._promise.reject(that.getError(errorMessage, error));
- });
- };
- function gatherBufferViewIdsFromProperties(properties, bufferViewIdSet) {
- for (const propertyId in properties) {
- if (properties.hasOwnProperty(propertyId)) {
- const property = properties[propertyId];
- const values = property.values;
- const arrayOffsets = property.arrayOffsets;
- const stringOffsets = property.stringOffsets;
- // Using an object like a mathematical set
- if (defined(values)) {
- bufferViewIdSet[values] = true;
- }
- if (defined(arrayOffsets)) {
- bufferViewIdSet[arrayOffsets] = true;
- }
- if (defined(stringOffsets)) {
- bufferViewIdSet[stringOffsets] = true;
- }
- }
- }
- }
- function gatherBufferViewIdsFromPropertiesLegacy(properties, bufferViewIdSet) {
- for (const propertyId in properties) {
- if (properties.hasOwnProperty(propertyId)) {
- const property = properties[propertyId];
- const bufferView = property.bufferView;
- const arrayOffsetBufferView = property.arrayOffsetBufferView;
- const stringOffsetBufferView = property.stringOffsetBufferView;
- // Using an object like a mathematical set
- if (defined(bufferView)) {
- bufferViewIdSet[bufferView] = true;
- }
- if (defined(arrayOffsetBufferView)) {
- bufferViewIdSet[arrayOffsetBufferView] = true;
- }
- if (defined(stringOffsetBufferView)) {
- bufferViewIdSet[stringOffsetBufferView] = true;
- }
- }
- }
- }
- function gatherUsedBufferViewIds(extension) {
- const propertyTables = extension.propertyTables;
- const bufferViewIdSet = {};
- if (defined(propertyTables)) {
- for (let i = 0; i < propertyTables.length; i++) {
- const propertyTable = propertyTables[i];
- gatherBufferViewIdsFromProperties(
- propertyTable.properties,
- bufferViewIdSet
- );
- }
- }
- return bufferViewIdSet;
- }
- function gatherUsedBufferViewIdsLegacy(extensionLegacy) {
- const featureTables = extensionLegacy.featureTables;
- const bufferViewIdSet = {};
- if (defined(featureTables)) {
- for (const featureTableId in featureTables) {
- if (featureTables.hasOwnProperty(featureTableId)) {
- const featureTable = featureTables[featureTableId];
- const properties = featureTable.properties;
- if (defined(properties)) {
- gatherBufferViewIdsFromPropertiesLegacy(properties, bufferViewIdSet);
- }
- }
- }
- }
- return bufferViewIdSet;
- }
- function loadBufferViews(structuralMetadataLoader) {
- let bufferViewIds;
- if (defined(structuralMetadataLoader._extension)) {
- bufferViewIds = gatherUsedBufferViewIds(
- structuralMetadataLoader._extension
- );
- } else {
- bufferViewIds = gatherUsedBufferViewIdsLegacy(
- structuralMetadataLoader._extensionLegacy
- );
- }
- // Load the buffer views
- const bufferViewPromises = [];
- const bufferViewLoaders = {};
- for (const bufferViewId in bufferViewIds) {
- if (bufferViewIds.hasOwnProperty(bufferViewId)) {
- const bufferViewLoader = ResourceCache.loadBufferView({
- gltf: structuralMetadataLoader._gltf,
- bufferViewId: parseInt(bufferViewId),
- gltfResource: structuralMetadataLoader._gltfResource,
- baseResource: structuralMetadataLoader._baseResource,
- });
- bufferViewPromises.push(bufferViewLoader.promise);
- structuralMetadataLoader._bufferViewLoaders.push(bufferViewLoader);
- bufferViewLoaders[bufferViewId] = bufferViewLoader;
- }
- }
- // Return a promise to a map of buffer view IDs to typed arrays
- return Promise.all(bufferViewPromises).then(function () {
- const bufferViews = {};
- for (const bufferViewId in bufferViewLoaders) {
- if (bufferViewLoaders.hasOwnProperty(bufferViewId)) {
- const bufferViewLoader = bufferViewLoaders[bufferViewId];
- // Copy the typed array and let the underlying ArrayBuffer be freed
- const bufferViewTypedArray = new Uint8Array(
- bufferViewLoader.typedArray
- );
- bufferViews[bufferViewId] = bufferViewTypedArray;
- }
- }
- // Buffer views can be unloaded after the data has been copied
- unloadBufferViews(structuralMetadataLoader);
- return bufferViews;
- });
- }
- function gatherUsedTextureIds(structuralMetadataExtension) {
- // Gather the used textures
- const textureIds = {};
- const propertyTextures = structuralMetadataExtension.propertyTextures;
- if (defined(propertyTextures)) {
- for (let i = 0; i < propertyTextures.length; i++) {
- const propertyTexture = propertyTextures[i];
- const properties = propertyTexture.properties;
- if (defined(properties)) {
- gatherTextureIdsFromProperties(properties, textureIds);
- }
- }
- }
- return textureIds;
- }
- function gatherTextureIdsFromProperties(properties, textureIds) {
- for (const propertyId in properties) {
- if (properties.hasOwnProperty(propertyId)) {
- // in EXT_structural_metadata the property is a valid textureInfo.
- const textureInfo = properties[propertyId];
- textureIds[textureInfo.index] = textureInfo;
- }
- }
- }
- function gatherUsedTextureIdsLegacy(extensionLegacy) {
- // Gather the used textures
- const textureIds = {};
- const featureTextures = extensionLegacy.featureTextures;
- if (defined(featureTextures)) {
- for (const featureTextureId in featureTextures) {
- if (featureTextures.hasOwnProperty(featureTextureId)) {
- const featureTexture = featureTextures[featureTextureId];
- const properties = featureTexture.properties;
- if (defined(properties)) {
- gatherTextureIdsFromPropertiesLegacy(properties, textureIds);
- }
- }
- }
- }
- return textureIds;
- }
- function gatherTextureIdsFromPropertiesLegacy(properties, textureIds) {
- for (const propertyId in properties) {
- if (properties.hasOwnProperty(propertyId)) {
- const property = properties[propertyId];
- const textureInfo = property.texture;
- textureIds[textureInfo.index] = textureInfo;
- }
- }
- }
- function loadTextures(structuralMetadataLoader) {
- let textureIds;
- if (defined(structuralMetadataLoader._extension)) {
- textureIds = gatherUsedTextureIds(structuralMetadataLoader._extension);
- } else {
- textureIds = gatherUsedTextureIdsLegacy(
- structuralMetadataLoader._extensionLegacy
- );
- }
- const gltf = structuralMetadataLoader._gltf;
- const gltfResource = structuralMetadataLoader._gltfResource;
- const baseResource = structuralMetadataLoader._baseResource;
- const supportedImageFormats = structuralMetadataLoader._supportedImageFormats;
- const asynchronous = structuralMetadataLoader._asynchronous;
- // Load the textures
- const texturePromises = [];
- const textureLoaders = {};
- for (const textureId in textureIds) {
- if (textureIds.hasOwnProperty(textureId)) {
- const textureLoader = ResourceCache.loadTexture({
- gltf: gltf,
- textureInfo: textureIds[textureId],
- gltfResource: gltfResource,
- baseResource: baseResource,
- supportedImageFormats: supportedImageFormats,
- asynchronous: asynchronous,
- });
- texturePromises.push(textureLoader.promise);
- structuralMetadataLoader._textureLoaders.push(textureLoader);
- textureLoaders[textureId] = textureLoader;
- }
- }
- // Return a promise to a map of texture IDs to Texture objects
- return Promise.all(texturePromises).then(function () {
- const textures = {};
- for (const textureId in textureLoaders) {
- if (textureLoaders.hasOwnProperty(textureId)) {
- const textureLoader = textureLoaders[textureId];
- textures[textureId] = textureLoader.texture;
- }
- }
- return textures;
- });
- }
- function loadSchema(structuralMetadataLoader) {
- const extension = defaultValue(
- structuralMetadataLoader._extension,
- structuralMetadataLoader._extensionLegacy
- );
- let schemaLoader;
- if (defined(extension.schemaUri)) {
- const resource = structuralMetadataLoader._baseResource.getDerivedResource({
- url: extension.schemaUri,
- });
- schemaLoader = ResourceCache.loadSchema({
- resource: resource,
- });
- } else {
- schemaLoader = ResourceCache.loadSchema({
- schema: extension.schema,
- });
- }
- structuralMetadataLoader._schemaLoader = schemaLoader;
- return schemaLoader.promise.then(function (schemaLoader) {
- return schemaLoader.schema;
- });
- }
- /**
- * Processes the resource until it becomes ready.
- *
- * @param {FrameState} frameState The frame state.
- * @private
- */
- GltfStructuralMetadataLoader.prototype.process = function (frameState) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("frameState", frameState);
- //>>includeEnd('debug');
- if (this._state !== ResourceLoaderState.LOADING) {
- return;
- }
- const textureLoaders = this._textureLoaders;
- const textureLoadersLength = textureLoaders.length;
- for (let i = 0; i < textureLoadersLength; ++i) {
- const textureLoader = textureLoaders[i];
- textureLoader.process(frameState);
- }
- };
- function unloadBufferViews(structuralMetadataLoader) {
- const bufferViewLoaders = structuralMetadataLoader._bufferViewLoaders;
- const bufferViewLoadersLength = bufferViewLoaders.length;
- for (let i = 0; i < bufferViewLoadersLength; ++i) {
- ResourceCache.unload(bufferViewLoaders[i]);
- }
- structuralMetadataLoader._bufferViewLoaders.length = 0;
- }
- function unloadTextures(structuralMetadataLoader) {
- const textureLoaders = structuralMetadataLoader._textureLoaders;
- const textureLoadersLength = textureLoaders.length;
- for (let i = 0; i < textureLoadersLength; ++i) {
- ResourceCache.unload(textureLoaders[i]);
- }
- structuralMetadataLoader._textureLoaders.length = 0;
- }
- /**
- * Unloads the resource.
- * @private
- */
- GltfStructuralMetadataLoader.prototype.unload = function () {
- unloadBufferViews(this);
- unloadTextures(this);
- if (defined(this._schemaLoader)) {
- ResourceCache.unload(this._schemaLoader);
- }
- this._schemaLoader = undefined;
- this._structuralMetadata = undefined;
- };
|