123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- 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 hasExtension from "./hasExtension.js";
- import MeshoptDecoder from "../ThirdParty/meshoptimizer.js";
- import ResourceLoader from "./ResourceLoader.js";
- import ResourceLoaderState from "./ResourceLoaderState.js";
- /**
- * Loads a glTF buffer view.
- * <p>
- * Implements the {@link ResourceLoader} interface.
- * </p>
- *
- * @alias GltfBufferViewLoader
- * @constructor
- * @augments ResourceLoader
- *
- * @param {Object} options Object with the following properties:
- * @param {ResourceCache} options.resourceCache The {@link ResourceCache} (to avoid circular dependencies).
- * @param {Object} options.gltf The glTF JSON.
- * @param {Number} options.bufferViewId The buffer view 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 {String} [options.cacheKey] The cache key of the resource.
- *
- * @private
- */
- export default function GltfBufferViewLoader(options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- const resourceCache = options.resourceCache;
- const gltf = options.gltf;
- const bufferViewId = options.bufferViewId;
- const gltfResource = options.gltfResource;
- const baseResource = options.baseResource;
- const cacheKey = options.cacheKey;
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.func("options.resourceCache", resourceCache);
- 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;
- let byteOffset = bufferView.byteOffset;
- let byteLength = bufferView.byteLength;
- let hasMeshopt = false;
- let meshoptByteStride;
- let meshoptCount;
- let meshoptMode;
- let meshoptFilter;
- if (hasExtension(bufferView, "EXT_meshopt_compression")) {
- const meshopt = bufferView.extensions.EXT_meshopt_compression;
- bufferId = meshopt.buffer;
- byteOffset = defaultValue(meshopt.byteOffset, 0);
- byteLength = meshopt.byteLength;
- hasMeshopt = true;
- meshoptByteStride = meshopt.byteStride;
- meshoptCount = meshopt.count;
- meshoptMode = meshopt.mode;
- meshoptFilter = defaultValue(meshopt.filter, "NONE");
- }
- const buffer = gltf.buffers[bufferId];
- this._hasMeshopt = hasMeshopt;
- this._meshoptByteStride = meshoptByteStride;
- this._meshoptCount = meshoptCount;
- this._meshoptMode = meshoptMode;
- this._meshoptFilter = meshoptFilter;
- this._resourceCache = resourceCache;
- this._gltfResource = gltfResource;
- this._baseResource = baseResource;
- this._buffer = buffer;
- this._bufferId = bufferId;
- this._byteOffset = byteOffset;
- this._byteLength = byteLength;
- this._cacheKey = cacheKey;
- this._bufferLoader = undefined;
- this._typedArray = undefined;
- this._state = ResourceLoaderState.UNLOADED;
- this._promise = defer();
- }
- if (defined(Object.create)) {
- GltfBufferViewLoader.prototype = Object.create(ResourceLoader.prototype);
- GltfBufferViewLoader.prototype.constructor = GltfBufferViewLoader;
- }
- Object.defineProperties(GltfBufferViewLoader.prototype, {
- /**
- * A promise that resolves to the resource when the resource is ready.
- *
- * @memberof GltfBufferViewLoader.prototype
- *
- * @type {Promise.<GltfBufferViewLoader>}
- * @readonly
- * @private
- */
- promise: {
- get: function () {
- return this._promise.promise;
- },
- },
- /**
- * The cache key of the resource.
- *
- * @memberof GltfBufferViewLoader.prototype
- *
- * @type {String}
- * @readonly
- * @private
- */
- cacheKey: {
- get: function () {
- return this._cacheKey;
- },
- },
- /**
- * The typed array containing buffer view data.
- *
- * @memberof GltfBufferViewLoader.prototype
- *
- * @type {Uint8Array}
- * @readonly
- * @private
- */
- typedArray: {
- get: function () {
- return this._typedArray;
- },
- },
- });
- /**
- * Loads the resource.
- * @private
- */
- GltfBufferViewLoader.prototype.load = function () {
- const bufferLoader = getBufferLoader(this);
- this._bufferLoader = bufferLoader;
- this._state = ResourceLoaderState.LOADING;
- const that = this;
- bufferLoader.promise
- .then(function () {
- if (that.isDestroyed()) {
- return;
- }
- const bufferTypedArray = bufferLoader.typedArray;
- const bufferViewTypedArray = new Uint8Array(
- bufferTypedArray.buffer,
- bufferTypedArray.byteOffset + that._byteOffset,
- that._byteLength
- );
- // Unload the buffer
- that.unload();
- that._typedArray = bufferViewTypedArray;
- if (that._hasMeshopt) {
- that._state = ResourceLoaderState.PROCESSING;
- } else {
- 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 buffer view";
- that._promise.reject(that.getError(errorMessage, error));
- });
- };
- function getBufferLoader(bufferViewLoader) {
- const resourceCache = bufferViewLoader._resourceCache;
- const buffer = bufferViewLoader._buffer;
- if (defined(buffer.uri)) {
- const baseResource = bufferViewLoader._baseResource;
- const resource = baseResource.getDerivedResource({
- url: buffer.uri,
- });
- return resourceCache.loadExternalBuffer({
- resource: resource,
- });
- }
- return resourceCache.loadEmbeddedBuffer({
- parentResource: bufferViewLoader._gltfResource,
- bufferId: bufferViewLoader._bufferId,
- });
- }
- /**
- * Processes the resources. For a BufferView that does not have the EXT_meshopt_compression extension, there
- * is no processing that needs to happen, so this function returns immediately.
- *
- * @param {FrameState} frameState The frame state.
- */
- GltfBufferViewLoader.prototype.process = function (frameState) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("frameState", frameState);
- //>>includeEnd('debug');
- if (!this._hasMeshopt) {
- return;
- }
- if (!defined(this._typedArray)) {
- return;
- }
- if (this._state !== ResourceLoaderState.PROCESSING) {
- return;
- }
- const count = this._meshoptCount;
- const byteStride = this._meshoptByteStride;
- const result = new Uint8Array(count * byteStride);
- MeshoptDecoder.decodeGltfBuffer(
- result,
- count,
- byteStride,
- this._typedArray,
- this._meshoptMode,
- this._meshoptFilter
- );
- this._typedArray = result;
- this._state = ResourceLoaderState.READY;
- this._promise.resolve(this);
- };
- /**
- * Unloads the resource.
- * @private
- */
- GltfBufferViewLoader.prototype.unload = function () {
- if (defined(this._bufferLoader)) {
- this._resourceCache.unload(this._bufferLoader);
- }
- this._bufferLoader = undefined;
- this._typedArray = undefined;
- };
|