| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601 |
- import Check from "../Core/Check.js";
- import Frozen from "../Core/Frozen.js";
- import defined from "../Core/defined.js";
- import DeveloperError from "../Core/DeveloperError.js";
- import getAbsoluteUri from "../Core/getAbsoluteUri.js";
- import GltfLoaderUtil from "./GltfLoaderUtil.js";
- import hasExtension from "./hasExtension.js";
-
- /**
- * Compute cache keys for resources in {@link ResourceCache}.
- *
- * @namespace ResourceCacheKey
- *
- * @private
- */
- const ResourceCacheKey = {};
-
- function getExternalResourceCacheKey(resource) {
- return getAbsoluteUri(resource.url);
- }
-
- function getBufferViewCacheKey(bufferView) {
- let { byteOffset, byteLength } = bufferView;
-
- if (hasExtension(bufferView, "EXT_meshopt_compression")) {
- const meshopt = bufferView.extensions.EXT_meshopt_compression;
- byteOffset = meshopt.byteOffset ?? 0;
- byteLength = meshopt.byteLength;
- }
-
- return `${byteOffset}-${byteOffset + byteLength}`;
- }
-
- function getAccessorCacheKey(accessor, bufferView) {
- const byteOffset = bufferView.byteOffset + accessor.byteOffset;
- const { componentType, type, count } = accessor;
- return `${byteOffset}-${componentType}-${type}-${count}`;
- }
-
- function getEmbeddedBufferCacheKey(parentResource, bufferId) {
- const parentCacheKey = getExternalResourceCacheKey(parentResource);
- return `${parentCacheKey}-buffer-id-${bufferId}`;
- }
-
- function getBufferCacheKey(buffer, bufferId, gltfResource, baseResource) {
- if (defined(buffer.uri)) {
- const resource = baseResource.getDerivedResource({
- url: buffer.uri,
- });
- return getExternalResourceCacheKey(resource);
- }
-
- return getEmbeddedBufferCacheKey(gltfResource, bufferId);
- }
-
- function getDracoCacheKey(gltf, draco, gltfResource, baseResource) {
- const bufferViewId = draco.bufferView;
- const bufferView = gltf.bufferViews[bufferViewId];
- const bufferId = bufferView.buffer;
- const buffer = gltf.buffers[bufferId];
-
- const bufferCacheKey = getBufferCacheKey(
- buffer,
- bufferId,
- gltfResource,
- baseResource,
- );
-
- const bufferViewCacheKey = getBufferViewCacheKey(bufferView);
-
- return `${bufferCacheKey}-range-${bufferViewCacheKey}`;
- }
-
- function getSpzCacheKey(gltf, primitive, gltfResource, baseResource) {
- const bufferViewId = 0;
- const bufferView = gltf.bufferViews[bufferViewId];
- const bufferId = bufferView.buffer;
- const buffer = gltf.buffers[bufferId];
-
- const bufferCacheKey = getBufferCacheKey(
- buffer,
- bufferId,
- gltfResource,
- baseResource,
- );
-
- const bufferViewCacheKey = getBufferViewCacheKey(bufferView);
-
- return `${bufferCacheKey}-range-${bufferViewCacheKey}`;
- }
-
- function getImageCacheKey(gltf, imageId, gltfResource, baseResource) {
- const image = gltf.images[imageId];
- const bufferViewId = image.bufferView;
- const uri = image.uri;
-
- if (defined(uri)) {
- const resource = baseResource.getDerivedResource({
- url: uri,
- });
- return getExternalResourceCacheKey(resource);
- }
-
- const bufferView = gltf.bufferViews[bufferViewId];
- const bufferId = bufferView.buffer;
- const buffer = gltf.buffers[bufferId];
-
- const bufferCacheKey = getBufferCacheKey(
- buffer,
- bufferId,
- gltfResource,
- baseResource,
- );
-
- const bufferViewCacheKey = getBufferViewCacheKey(bufferView);
-
- return `${bufferCacheKey}-range-${bufferViewCacheKey}`;
- }
-
- function getSamplerCacheKey(gltf, textureInfo) {
- const sampler = GltfLoaderUtil.createSampler({
- gltf: gltf,
- textureInfo: textureInfo,
- });
-
- return `${sampler.wrapS}-${sampler.wrapT}-${sampler.minificationFilter}-${sampler.magnificationFilter}`;
- }
-
- /**
- * Gets the schema cache key.
- *
- * @param {object} options Object with the following properties:
- * @param {object} [options.schema] An object that explicitly defines a schema JSON. Mutually exclusive with options.resource.
- * @param {Resource} [options.resource] The {@link Resource} pointing to the schema JSON. Mutually exclusive with options.schema.
- *
- * @returns {string} The schema cache key.
- *
- * @exception {DeveloperError} One of options.schema and options.resource must be defined.
- * @private
- */
- ResourceCacheKey.getSchemaCacheKey = function (options) {
- const { schema, resource } = options;
-
- //>>includeStart('debug', pragmas.debug);
- if (defined(schema) === defined(resource)) {
- throw new DeveloperError(
- "One of options.schema and options.resource must be defined.",
- );
- }
- //>>includeEnd('debug');
-
- if (defined(schema)) {
- return `embedded-schema:${JSON.stringify(schema)}`;
- }
-
- return `external-schema:${getExternalResourceCacheKey(resource)}`;
- };
-
- /**
- * Gets the external buffer cache key.
- *
- * @param {object} options Object with the following properties:
- * @param {Resource} options.resource The {@link Resource} pointing to the external buffer.
- *
- * @returns {string} The external buffer cache key.
- * @private
- */
- ResourceCacheKey.getExternalBufferCacheKey = function (options) {
- options = options ?? Frozen.EMPTY_OBJECT;
- const { resource } = options;
-
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options.resource", resource);
- //>>includeEnd('debug');
-
- return `external-buffer:${getExternalResourceCacheKey(resource)}`;
- };
-
- /**
- * Gets the embedded buffer cache key.
- *
- * @param {object} options Object with the following properties:
- * @param {Resource} options.parentResource The {@link Resource} containing the embedded buffer.
- * @param {number} options.bufferId A unique identifier of the embedded buffer within the parent resource.
- *
- * @returns {string} The embedded buffer cache key.
- * @private
- */
- ResourceCacheKey.getEmbeddedBufferCacheKey = function (options) {
- options = options ?? Frozen.EMPTY_OBJECT;
- const { parentResource, bufferId } = options;
-
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options.parentResource", parentResource);
- Check.typeOf.number("options.bufferId", bufferId);
- //>>includeEnd('debug');
-
- return `embedded-buffer:${getEmbeddedBufferCacheKey(
- parentResource,
- bufferId,
- )}`;
- };
-
- /**
- * Gets the glTF cache key.
- *
- * @param {object} options Object with the following properties:
- * @param {Resource} options.gltfResource The {@link Resource} containing the glTF.
- *
- * @returns {string} The glTF cache key.
- * @private
- */
- ResourceCacheKey.getGltfCacheKey = function (options) {
- options = options ?? Frozen.EMPTY_OBJECT;
- const { gltfResource } = options;
-
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options.gltfResource", gltfResource);
- //>>includeEnd('debug');
-
- return `gltf:${getExternalResourceCacheKey(gltfResource)}`;
- };
-
- /**
- * Gets the buffer view cache key.
- *
- * @param {object} options Object with the following properties:
- * @param {object} options.gltf The glTF JSON.
- * @param {number} options.bufferViewId The bufferView 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.
- *
- * @returns {string} The buffer view cache key.
- * @private
- */
- ResourceCacheKey.getBufferViewCacheKey = function (options) {
- options = options ?? Frozen.EMPTY_OBJECT;
- const { gltf, bufferViewId, gltfResource, baseResource } = options;
-
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options.gltf", gltf);
- Check.typeOf.number("options.bufferViewId", bufferViewId);
- Check.typeOf.object("options.gltfResource", gltfResource);
- Check.typeOf.object("options.baseResource", baseResource);
- //>>includeEnd('debug');
-
- const bufferView = gltf.bufferViews[bufferViewId];
- let bufferId = bufferView.buffer;
- const buffer = gltf.buffers[bufferId];
- if (hasExtension(bufferView, "EXT_meshopt_compression")) {
- const meshopt = bufferView.extensions.EXT_meshopt_compression;
- bufferId = meshopt.buffer;
- }
-
- const bufferCacheKey = getBufferCacheKey(
- buffer,
- bufferId,
- gltfResource,
- baseResource,
- );
-
- const bufferViewCacheKey = getBufferViewCacheKey(bufferView);
-
- return `buffer-view:${bufferCacheKey}-range-${bufferViewCacheKey}`;
- };
-
- /**
- * Gets the Draco cache key.
- *
- * @param {object} options Object with the following properties:
- * @param {object} options.gltf The glTF JSON.
- * @param {object} options.draco The Draco extension object.
- * @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.
- *
- * @returns {string} The Draco cache key.
- * @private
- */
- ResourceCacheKey.getDracoCacheKey = function (options) {
- options = options ?? Frozen.EMPTY_OBJECT;
- const { gltf, draco, gltfResource, baseResource } = options;
-
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options.gltf", gltf);
- Check.typeOf.object("options.draco", draco);
- Check.typeOf.object("options.gltfResource", gltfResource);
- Check.typeOf.object("options.baseResource", baseResource);
- //>>includeEnd('debug');
-
- return `draco:${getDracoCacheKey(gltf, draco, gltfResource, baseResource)}`;
- };
-
- ResourceCacheKey.getSpzCacheKey = function (options) {
- options = options ?? Frozen.EMPTY_OBJECT;
- const { gltf, primitive, gltfResource, baseResource } = options;
-
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options.gltf", gltf);
- Check.typeOf.object("options.primitive", primitive);
- Check.typeOf.object("options.gltfResource", gltfResource);
- Check.typeOf.object("options.baseResource", baseResource);
- //>>includeEnd('debug');
-
- return `spz:${getSpzCacheKey(gltf, primitive, gltfResource, baseResource)}`;
- };
- /**
- * Gets the vertex buffer cache key.
- *
- * @param {object} options Object with the following properties:
- * @param {object} options.gltf The glTF JSON.
- * @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 {FrameState} options.frameState The frame state.
- * @param {number} [options.bufferViewId] The bufferView ID corresponding to the vertex buffer.
- * @param {object} [options.draco] The Draco extension object.
- * @param {string} [options.attributeSemantic] The attribute semantic, e.g. POSITION or NORMAL.
- * @param {boolean} [options.dequantize=false] Determines whether or not the vertex buffer will be dequantized on the CPU.
- * @param {boolean} [options.loadBuffer=false] Load vertex buffer as a GPU vertex buffer.
- * @param {boolean} [options.loadTypedArray=false] Load vertex buffer as a typed array.
- * @exception {DeveloperError} One of options.bufferViewId and options.draco must be defined.
- * @exception {DeveloperError} When options.draco is defined options.attributeSemantic must also be defined.
- *
- * @returns {string} The vertex buffer cache key.
- * @private
- */
- ResourceCacheKey.getVertexBufferCacheKey = function (options) {
- options = options ?? Frozen.EMPTY_OBJECT;
- const {
- gltf,
- gltfResource,
- baseResource,
- frameState,
- bufferViewId,
- draco,
- spz,
- attributeSemantic,
- dequantize = false,
- loadBuffer = false,
- loadTypedArray = false,
- } = options;
-
- //>>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.frameState", frameState);
-
- const hasBufferViewId = defined(bufferViewId);
- const hasDraco = hasDracoCompression(draco, attributeSemantic);
- const hasAttributeSemantic = defined(attributeSemantic);
- const hasSpz = defined(spz);
-
- if (hasBufferViewId === (hasDraco !== hasSpz)) {
- throw new DeveloperError(
- "One of options.bufferViewId and options.draco must be defined.",
- );
- }
-
- if (hasDraco && !hasAttributeSemantic) {
- throw new DeveloperError(
- "When options.draco is defined options.attributeSemantic must also be defined.",
- );
- }
-
- if (hasDraco) {
- Check.typeOf.object("options.draco", draco);
- Check.typeOf.string("options.attributeSemantic", attributeSemantic);
- }
-
- if (!loadBuffer && !loadTypedArray) {
- throw new DeveloperError(
- "At least one of loadBuffer and loadTypedArray must be true.",
- );
- }
- //>>includeEnd('debug');
-
- let cacheKeySuffix = "";
- if (dequantize) {
- cacheKeySuffix += "-dequantize";
- }
-
- if (loadBuffer) {
- cacheKeySuffix += "-buffer";
- cacheKeySuffix += `-context-${frameState.context.id}`;
- }
-
- if (loadTypedArray) {
- cacheKeySuffix += "-typed-array";
- }
-
- if (defined(draco)) {
- const dracoCacheKey = getDracoCacheKey(
- gltf,
- draco,
- gltfResource,
- baseResource,
- );
- return `vertex-buffer:${dracoCacheKey}-draco-${attributeSemantic}${cacheKeySuffix}`;
- }
-
- if (spz) {
- const spzCacheKey = getSpzCacheKey(gltf, spz, gltfResource, baseResource);
- return `vertex-buffer:${spzCacheKey}-spz-${attributeSemantic}${cacheKeySuffix}`;
- }
-
- const bufferView = gltf.bufferViews[bufferViewId];
- const bufferId = bufferView.buffer;
- const buffer = gltf.buffers[bufferId];
-
- const bufferCacheKey = getBufferCacheKey(
- buffer,
- bufferId,
- gltfResource,
- baseResource,
- );
-
- const bufferViewCacheKey = getBufferViewCacheKey(bufferView);
-
- return `vertex-buffer:${bufferCacheKey}-range-${bufferViewCacheKey}${cacheKeySuffix}`;
- };
-
- function hasDracoCompression(draco, semantic) {
- return (
- defined(draco) &&
- defined(draco.attributes) &&
- defined(draco.attributes[semantic])
- );
- }
-
- /**
- * Gets the index buffer cache key.
- *
- * @param {object} options Object with the following properties:
- * @param {object} options.gltf The glTF JSON.
- * @param {number} options.accessorId The accessor ID corresponding to the index buffer.
- * @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 {FrameState} options.frameState The frame state.
- * @param {object} [options.draco] The Draco extension object.
- * @param {boolean} [options.loadBuffer=false] Load index buffer as a GPU index buffer.
- * @param {boolean} [options.loadTypedArray=false] Load index buffer as a typed array.
- *
- * @returns {string} The index buffer cache key.
- * @private
- */
- ResourceCacheKey.getIndexBufferCacheKey = function (options) {
- options = options ?? Frozen.EMPTY_OBJECT;
- const {
- gltf,
- accessorId,
- gltfResource,
- baseResource,
- frameState,
- draco,
- loadBuffer = false,
- loadTypedArray = false,
- } = options;
-
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options.gltf", gltf);
- Check.typeOf.number("options.accessorId", accessorId);
- Check.typeOf.object("options.gltfResource", gltfResource);
- Check.typeOf.object("options.baseResource", baseResource);
- Check.typeOf.object("options.frameState", frameState);
-
- if (!loadBuffer && !loadTypedArray) {
- throw new DeveloperError(
- "At least one of loadBuffer and loadTypedArray must be true.",
- );
- }
- //>>includeEnd('debug');
-
- let cacheKeySuffix = "";
- if (loadBuffer) {
- cacheKeySuffix += "-buffer";
- cacheKeySuffix += `-context-${frameState.context.id}`;
- }
-
- if (loadTypedArray) {
- cacheKeySuffix += "-typed-array";
- }
-
- if (defined(draco)) {
- const dracoCacheKey = getDracoCacheKey(
- gltf,
- draco,
- gltfResource,
- baseResource,
- );
- return `index-buffer:${dracoCacheKey}-draco${cacheKeySuffix}`;
- }
-
- const accessor = gltf.accessors[accessorId];
- const bufferViewId = accessor.bufferView;
- const bufferView = gltf.bufferViews[bufferViewId];
- const bufferId = bufferView.buffer;
- const buffer = gltf.buffers[bufferId];
-
- const bufferCacheKey = getBufferCacheKey(
- buffer,
- bufferId,
- gltfResource,
- baseResource,
- );
-
- const accessorCacheKey = getAccessorCacheKey(accessor, bufferView);
-
- return `index-buffer:${bufferCacheKey}-accessor-${accessorCacheKey}${cacheKeySuffix}`;
- };
-
- /**
- * Gets the image cache key.
- *
- * @param {object} options Object with the following properties:
- * @param {object} options.gltf The glTF JSON.
- * @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.
- *
- * @returns {string} The image cache key.
- * @private
- */
- ResourceCacheKey.getImageCacheKey = function (options) {
- options = options ?? Frozen.EMPTY_OBJECT;
- const { gltf, imageId, gltfResource, baseResource } = options;
-
- //>>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);
- //>>includeEnd('debug');
-
- const imageCacheKey = getImageCacheKey(
- gltf,
- imageId,
- gltfResource,
- baseResource,
- );
-
- return `image:${imageCacheKey}`;
- };
-
- /**
- * Gets the texture cache key.
- *
- * @param {object} options Object with the following properties:
- * @param {object} options.gltf The glTF JSON.
- * @param {object} options.textureInfo The texture info object.
- * @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 {FrameState} options.frameState The frame state.
- *
- * @returns {string} The texture cache key.
- * @private
- */
- ResourceCacheKey.getTextureCacheKey = function (options) {
- options = options ?? Frozen.EMPTY_OBJECT;
- const {
- gltf,
- textureInfo,
- gltfResource,
- baseResource,
- supportedImageFormats,
- frameState,
- } = options;
-
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options.gltf", gltf);
- Check.typeOf.object("options.textureInfo", textureInfo);
- Check.typeOf.object("options.gltfResource", gltfResource);
- Check.typeOf.object("options.baseResource", baseResource);
- Check.typeOf.object("options.supportedImageFormats", supportedImageFormats);
- Check.typeOf.object("options.frameState", frameState);
- //>>includeEnd('debug');
-
- const textureId = textureInfo.index;
-
- const imageId = GltfLoaderUtil.getImageIdFromTexture({
- gltf: gltf,
- textureId: textureId,
- supportedImageFormats: supportedImageFormats,
- });
-
- const imageCacheKey = getImageCacheKey(
- gltf,
- imageId,
- gltfResource,
- baseResource,
- );
-
- // Include the sampler cache key in the texture cache key since textures and
- // samplers are coupled in WebGL 1. When upgrading to WebGL 2 consider
- // removing the sampleCacheKey here.
- const samplerCacheKey = getSamplerCacheKey(gltf, textureInfo);
-
- return `texture:${imageCacheKey}-sampler-${samplerCacheKey}-context-${frameState.context.id}`;
- };
-
- export default ResourceCacheKey;
|