133 lines
5.3 KiB
JavaScript
133 lines
5.3 KiB
JavaScript
/*
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* 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
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
Filament.onReadyListeners = [];
|
|
|
|
Filament.isReady = false;
|
|
|
|
/// init ::function:: Downloads assets, loads the Filament module, and invokes a callback when done.
|
|
///
|
|
/// All JavaScript clients must call the init function, passing in a list of asset URL's and a
|
|
/// callback. This callback gets invoked only after all assets have been downloaded and the Filament
|
|
/// WebAssembly module has been loaded. Clients should only pass asset URL's that absolutely must
|
|
/// be ready at initialization time.
|
|
///
|
|
/// When the callback is called, each downloaded asset is available in the `Filament.assets` global
|
|
/// object, which contains a mapping from URL's to Uint8Array objects.
|
|
///
|
|
/// assets ::argument:: Array of strings containing URL's of required assets.
|
|
/// onready ::argument:: callback that gets invoked after all assets have been downloaded and the \
|
|
/// Filament WebAssembly module has been loaded.
|
|
Filament.init = (assets, onready) => {
|
|
if (onready) {
|
|
Filament.onReadyListeners.push(onready);
|
|
}
|
|
if (Filament.initialized) {
|
|
console.assert(!assets || assets.length == 0, "Assets can be specified only with the first call to init.");
|
|
return;
|
|
};
|
|
Filament.initialized = true;
|
|
|
|
Filament.assets = {};
|
|
|
|
// Usage of glmatrix is optional. If it exists, then go ahead and augment it with some
|
|
// useful math functions.
|
|
if (typeof glMatrix !== 'undefined') {
|
|
Filament.loadMathExtensions();
|
|
}
|
|
|
|
// One task for compiling & loading the wasm file, plus one task for each asset.
|
|
let remainingTasks = 1 + assets.length;
|
|
const taskFinished = () => {
|
|
if (--remainingTasks == 0) {
|
|
for (const callback of Filament.onReadyListeners) {
|
|
callback();
|
|
}
|
|
Filament.isReady = true;
|
|
}
|
|
};
|
|
|
|
// Issue a fetch for each asset.
|
|
Filament.fetch(assets, null, taskFinished);
|
|
|
|
// Emscripten creates a global function called "Filament" that returns a promise that
|
|
// resolves to a module. Here we replace the function with the module. Note that our
|
|
// TypeScript bindings assume that Filament is a namespace, not a function.
|
|
Filament().then(module => {
|
|
|
|
// Merge our extension functions into the emscripten module, not the other
|
|
// way around, because Emscripten potentially replaces the HEAPU8 views in
|
|
// the original module object (e.g. if it needs to grow the heap).
|
|
Filament = Object.assign(module, Filament);
|
|
|
|
// At this point, emscripten has finished compiling and instancing the WebAssembly module.
|
|
// The JS classes that correspond to core Filament classes (e.g., Engine) are not guaranteed
|
|
// to exist until now.
|
|
|
|
Filament.loadClassExtensions();
|
|
taskFinished();
|
|
});
|
|
};
|
|
|
|
Filament.clearAssetCache = () => {
|
|
for (const key in Filament.assets) delete Filament.assets[key];
|
|
};
|
|
|
|
/// fetch ::function:: Downloads assets and invokes a callback when done.
|
|
///
|
|
/// This utility consumes an array of URI strings and invokes callbacks after each asset is
|
|
/// downloaded. Additionally, each downloaded asset becomes available in the `Filament.assets`
|
|
/// global object, which is a mapping from URI strings to `Uint8Array`. If desired, clients can
|
|
/// pre-populate entries in `Filament.assets` to circumvent HTTP requests (this should be done after
|
|
/// calling `Filament.init`).
|
|
///
|
|
/// This function is used internally by `Filament.init` and `gltfio$FilamentAsset.loadResources`.
|
|
///
|
|
/// assets ::argument:: Array of strings containing URL's of required assets.
|
|
/// onDone ::argument:: callback that gets invoked after all assets have been downloaded.
|
|
/// onFetched ::argument:: optional callback that's invoked after each asset is downloaded.
|
|
Filament.fetch = (assets, onDone, onFetched) => {
|
|
let remainingAssets = assets.length;
|
|
assets.forEach(name => {
|
|
|
|
// Check if a buffer already exists in case the client wishes
|
|
// to provide its own data rather than using a HTTP request.
|
|
if (Filament.assets[name]) {
|
|
if (onFetched) {
|
|
onFetched(name);
|
|
}
|
|
if (--remainingAssets === 0 && onDone) {
|
|
onDone();
|
|
}
|
|
} else {
|
|
fetch(name).then(response => {
|
|
if (!response.ok) {
|
|
throw new Error(name);
|
|
}
|
|
return response.arrayBuffer();
|
|
}).then(arrayBuffer => {
|
|
Filament.assets[name] = new Uint8Array(arrayBuffer);
|
|
if (onFetched) {
|
|
onFetched(name);
|
|
}
|
|
if (--remainingAssets === 0 && onDone) {
|
|
onDone();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
};
|