gltfio: Introduce the asynchronous API and use it.

We were already using jobs for decoding PNG and JPEG files, but we were
doing a join. This add three methods to ResourceLoader that allow
clients to amortize the decoding process across multiple frames, even on
single-threaded platforms like WebGL.

This PR adds async loading to the following demos:
- samples/gltf_viewer (now shows a progress bar in the UI)
- android/sample-gltf-viewer
- web/samples/helmet.html

Fixes #1876.
This commit is contained in:
Philip Rideout
2020-01-29 11:23:14 -08:00
parent 503e66790b
commit c681cd243a
9 changed files with 280 additions and 77 deletions

View File

@@ -53,6 +53,7 @@ struct App {
MaterialProvider* materials;
MaterialSource materialSource = GENERATE_SHADERS;
bool actualSize = false;
gltfio::ResourceLoader* resourceLoader = nullptr;
};
static const char* DEFAULT_IBL = "venetian_crossroads_2k";
@@ -199,15 +200,15 @@ int main(int argc, char** argv) {
configuration.gltfPath = filename.getAbsolutePath();
configuration.normalizeSkinningWeights = true;
configuration.recomputeBoundingBoxes = false;
gltfio::ResourceLoader(configuration).loadResources(app.asset);
if (!app.resourceLoader) {
app.resourceLoader = new gltfio::ResourceLoader(configuration);
}
app.resourceLoader->asyncBeginLoad(app.asset);
// Load animation data then free the source hierarchy.
app.asset->getAnimator();
app.asset->releaseSourceData();
// Add the renderables to the scene.
app.viewer->setAsset(app.asset, !app.actualSize);
auto ibl = FilamentApp::get().getIBL();
if (ibl) {
app.viewer->setIndirectLight(ibl->getIndirectLight(), ibl->getSphericalHarmonics());
@@ -231,6 +232,10 @@ int main(int argc, char** argv) {
loadResources(filename);
app.viewer->setUiCallback([&app, scene] () {
float progress = app.resourceLoader->asyncGetLoadProgress();
if (progress < 1.0) {
ImGui::ProgressBar(progress);
}
if (ImGui::CollapsingHeader("Stats")) {
ImGui::Text("%zu entities in the asset", app.asset->getEntityCount());
ImGui::Text("%zu renderables (excluding UI)", scene->getRenderableCount());
@@ -253,6 +258,13 @@ int main(int argc, char** argv) {
};
auto animate = [&app](Engine* engine, View* view, double now) {
app.resourceLoader->asyncUpdateLoad();
// Add the renderables to the scene after the textures have finished loading.
if (app.resourceLoader->asyncGetLoadProgress() == 1.0f) {
app.viewer->setAsset(app.asset, !app.actualSize);
}
app.viewer->applyAnimation(now);
};