Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 57 additions & 63 deletions packages/engine/Source/Scene/BufferLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,30 @@ import ResourceLoaderState from "./ResourceLoaderState.js";
*
* @private
*/
function BufferLoader(options) {
options = options ?? Frozen.EMPTY_OBJECT;
const typedArray = options.typedArray;
const resource = options.resource;
const cacheKey = options.cacheKey;
class BufferLoader extends ResourceLoader {
constructor(options) {
super();

//>>includeStart('debug', pragmas.debug);
if (defined(typedArray) === defined(resource)) {
throw new DeveloperError(
"One of options.typedArray and options.resource must be defined.",
);
}
//>>includeEnd('debug');
options = options ?? Frozen.EMPTY_OBJECT;
const typedArray = options.typedArray;
const resource = options.resource;
const cacheKey = options.cacheKey;

this._typedArray = typedArray;
this._resource = resource;
this._cacheKey = cacheKey;
this._state = ResourceLoaderState.UNLOADED;
this._promise = undefined;
}
//>>includeStart('debug', pragmas.debug);
if (defined(typedArray) === defined(resource)) {
throw new DeveloperError(
"One of options.typedArray and options.resource must be defined.",
);
}
//>>includeEnd('debug');

if (defined(Object.create)) {
BufferLoader.prototype = Object.create(ResourceLoader.prototype);
BufferLoader.prototype.constructor = BufferLoader;
}
this._typedArray = typedArray;
this._resource = resource;
this._cacheKey = cacheKey;
this._state = ResourceLoaderState.UNLOADED;
this._promise = undefined;
}

Object.defineProperties(BufferLoader.prototype, {
/**
* The cache key of the resource.
*
Expand All @@ -59,11 +56,10 @@ Object.defineProperties(BufferLoader.prototype, {
* @readonly
* @private
*/
cacheKey: {
get: function () {
return this._cacheKey;
},
},
get cacheKey() {
return this._cacheKey;
}

/**
* The typed array containing the embedded buffer contents.
*
Expand All @@ -73,31 +69,45 @@ Object.defineProperties(BufferLoader.prototype, {
* @readonly
* @private
*/
typedArray: {
get: function () {
return this._typedArray;
},
},
});
get typedArray() {
return this._typedArray;
}

/**
* Loads the resource.
* @returns {Promise<BufferLoader>} A promise which resolves to the loader when the resource loading is completed.
* @private
*/
BufferLoader.prototype.load = async function () {
if (defined(this._promise)) {
/**
* Loads the resource.
* @returns {Promise<BufferLoader>} A promise which resolves to the loader when the resource loading is completed.
* @private
*/
async load() {
if (defined(this._promise)) {
return this._promise;
}

if (defined(this._typedArray)) {
this._promise = Promise.resolve(this);
return this._promise;
}

this._promise = loadExternalBuffer(this);
return this._promise;
}

if (defined(this._typedArray)) {
this._promise = Promise.resolve(this);
return this._promise;
/**
* Exposed for testing
* @private
*/
static _fetchArrayBuffer(resource) {
return resource.fetchArrayBuffer();
}

this._promise = loadExternalBuffer(this);
return this._promise;
};
/**
* Unloads the resource.
* @private
*/
unload() {
this._typedArray = undefined;
}
}

async function loadExternalBuffer(bufferLoader) {
const resource = bufferLoader._resource;
Expand All @@ -122,20 +132,4 @@ async function loadExternalBuffer(bufferLoader) {
}
}

/**
* Exposed for testing
* @private
*/
BufferLoader._fetchArrayBuffer = function (resource) {
return resource.fetchArrayBuffer();
};

/**
* Unloads the resource.
* @private
*/
BufferLoader.prototype.unload = function () {
this._typedArray = undefined;
};

export default BufferLoader;
157 changes: 79 additions & 78 deletions packages/engine/Source/Scene/DracoLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,94 +6,95 @@ import TaskProcessor from "../Core/TaskProcessor.js";
/**
* @private
*/
function DracoLoader() {}
class DracoLoader {
static _getDecoderTaskProcessor() {
if (!defined(DracoLoader._decoderTaskProcessor)) {
const processor = new TaskProcessor(
"decodeDraco",
DracoLoader._maxDecodingConcurrency,
);
processor
.initWebAssemblyModule({
wasmBinaryFile: "ThirdParty/draco_decoder.wasm",
})
.then(function (result) {
if (result) {
DracoLoader._taskProcessorReady = true;
} else {
DracoLoader._error = new RuntimeError(
"Draco decoder could not be initialized.",
);
}
})
.catch((error) => {
DracoLoader._error = error;
});
DracoLoader._decoderTaskProcessor = processor;
}

// Maximum concurrency to use when decoding draco models
DracoLoader._maxDecodingConcurrency = Math.max(
FeatureDetection.hardwareConcurrency - 1,
1,
);

// Exposed for testing purposes
DracoLoader._decoderTaskProcessor = undefined;
DracoLoader._taskProcessorReady = false;
DracoLoader._error = undefined;
DracoLoader._getDecoderTaskProcessor = function () {
if (!defined(DracoLoader._decoderTaskProcessor)) {
const processor = new TaskProcessor(
"decodeDraco",
DracoLoader._maxDecodingConcurrency,
);
processor
.initWebAssemblyModule({
wasmBinaryFile: "ThirdParty/draco_decoder.wasm",
})
.then(function (result) {
if (result) {
DracoLoader._taskProcessorReady = true;
} else {
DracoLoader._error = new RuntimeError(
"Draco decoder could not be initialized.",
);
}
})
.catch((error) => {
DracoLoader._error = error;
});
DracoLoader._decoderTaskProcessor = processor;
return DracoLoader._decoderTaskProcessor;
}

return DracoLoader._decoderTaskProcessor;
};
/**
* Decodes a compressed point cloud. Returns undefined if the task cannot be scheduled.
* @private
*
* @exception {RuntimeError} Draco decoder could not be initialized.
*/
static decodePointCloud(parameters) {
const decoderTaskProcessor = DracoLoader._getDecoderTaskProcessor();
if (defined(DracoLoader._error)) {
throw DracoLoader._error;
}

/**
* Decodes a compressed point cloud. Returns undefined if the task cannot be scheduled.
* @private
*
* @exception {RuntimeError} Draco decoder could not be initialized.
*/
DracoLoader.decodePointCloud = function (parameters) {
const decoderTaskProcessor = DracoLoader._getDecoderTaskProcessor();
if (defined(DracoLoader._error)) {
throw DracoLoader._error;
if (!DracoLoader._taskProcessorReady) {
// The task processor is not ready to schedule tasks
return;
}
return decoderTaskProcessor.scheduleTask(parameters, [
parameters.buffer.buffer,
]);
}

if (!DracoLoader._taskProcessorReady) {
// The task processor is not ready to schedule tasks
return;
}
return decoderTaskProcessor.scheduleTask(parameters, [
parameters.buffer.buffer,
]);
};
/**
* Decodes a buffer view. Returns undefined if the task cannot be scheduled.
*
* @param {object} options Object with the following properties:
* @param {Uint8Array} options.array The typed array containing the buffer view data.
* @param {object} options.bufferView The glTF buffer view object.
* @param {Object<string, number>} options.compressedAttributes The compressed attributes.
* @param {boolean} options.dequantizeInShader Whether POSITION and NORMAL attributes should be dequantized on the GPU.
*
* @returns {Promise} A promise that resolves to the decoded indices and attributes.
* @private
*
* @exception {RuntimeError} Draco decoder could not be initialized.
*/
static decodeBufferView(options) {
const decoderTaskProcessor = DracoLoader._getDecoderTaskProcessor();

/**
* Decodes a buffer view. Returns undefined if the task cannot be scheduled.
*
* @param {object} options Object with the following properties:
* @param {Uint8Array} options.array The typed array containing the buffer view data.
* @param {object} options.bufferView The glTF buffer view object.
* @param {Object<string, number>} options.compressedAttributes The compressed attributes.
* @param {boolean} options.dequantizeInShader Whether POSITION and NORMAL attributes should be dequantized on the GPU.
*
* @returns {Promise} A promise that resolves to the decoded indices and attributes.
* @private
*
* @exception {RuntimeError} Draco decoder could not be initialized.
*/
DracoLoader.decodeBufferView = function (options) {
const decoderTaskProcessor = DracoLoader._getDecoderTaskProcessor();
if (defined(DracoLoader._error)) {
throw DracoLoader._error;
}

if (defined(DracoLoader._error)) {
throw DracoLoader._error;
}
if (!DracoLoader._taskProcessorReady) {
// The task processor is not ready to schedule tasks
return;
}

if (!DracoLoader._taskProcessorReady) {
// The task processor is not ready to schedule tasks
return;
return decoderTaskProcessor.scheduleTask(options, [options.array.buffer]);
}
}

// Maximum concurrency to use when decoding draco models
DracoLoader._maxDecodingConcurrency = Math.max(
FeatureDetection.hardwareConcurrency - 1,
1,
);

return decoderTaskProcessor.scheduleTask(options, [options.array.buffer]);
};
// Exposed for testing purposes
DracoLoader._decoderTaskProcessor = undefined;
DracoLoader._taskProcessorReady = false;
DracoLoader._error = undefined;

export default DracoLoader;
Loading