From e8e847a66208cd78c511d438850e99bcdee72ae7 Mon Sep 17 00:00:00 2001 From: Philip Rideout Date: Sat, 1 Feb 2020 16:48:13 -0800 Subject: [PATCH] gltfio: various cleanup in response to PR review --- .../filament/gltfio/FilamentAsset.java | 5 +++ libs/gltfio/include/gltfio/FilamentAsset.h | 9 ++-- libs/gltfio/include/gltfio/SimpleViewer.h | 13 +++--- libs/gltfio/src/DependencyGraph.cpp | 10 ++--- libs/gltfio/src/DependencyGraph.h | 42 +++++++++++-------- samples/gltf_baker.cpp | 2 +- samples/gltf_viewer.cpp | 2 +- 7 files changed, 48 insertions(+), 35 deletions(-) diff --git a/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentAsset.java b/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentAsset.java index c4fb003030..3e6a228e3f 100644 --- a/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentAsset.java +++ b/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/FilamentAsset.java @@ -64,8 +64,13 @@ public class FilamentAsset { /** * Pops a ready renderable off the queue, or returns 0 if no renderables have become ready. * + * NOTE: To determine the progress percentage or completion status, please use + * ResourceLoader#asyncGetLoadProgress. + * * This helper method allows clients to progressively add renderables to the scene as textures * gradually become ready through asynchronous loading. + * + * See also ResourceLoader#asyncBeginLoad. */ public @Entity int popRenderable() { return nPopRenderable(mNativeObject); diff --git a/libs/gltfio/include/gltfio/FilamentAsset.h b/libs/gltfio/include/gltfio/FilamentAsset.h index f341f01fac..65f66c1dfb 100644 --- a/libs/gltfio/include/gltfio/FilamentAsset.h +++ b/libs/gltfio/include/gltfio/FilamentAsset.h @@ -75,9 +75,12 @@ public: /** * Pops a ready renderable off the queue, or returns 0 if no renderables have become ready. * - * This helper method allows clients to progressively add renderables to the scene as textures - * gradually become ready through asynchronous loading. For example, on every frame progressive - * applications can do something like this: + * NOTE: To determine the progress percentage or completion status, please use + * ResourceLoader#asyncGetLoadProgress. + * + * This method allows clients to progressively add the asset's renderables to the scene as + * textures gradually become ready through asynchronous loading. For example, on every frame + * progressive applications can do something like this: * * while (utils::Entity e = popRenderable()) { scene.addEntity(e); } * diff --git a/libs/gltfio/include/gltfio/SimpleViewer.h b/libs/gltfio/include/gltfio/SimpleViewer.h index 3a3b038982..c66a6d9917 100644 --- a/libs/gltfio/include/gltfio/SimpleViewer.h +++ b/libs/gltfio/include/gltfio/SimpleViewer.h @@ -69,17 +69,16 @@ public: ~SimpleViewer(); /** - * Sets or changes the asset that is being viewed. + * Adds the asset's ready-to-render entities into the scene and optionally transforms the root + * node to make it fit into a unit cube at the origin. * - * This adds all the asset's entities into the scene and optionally transforms the asset to make - * it fit into a unit cube at the origin. The viewer does not claim ownership over the asset or - * its entities. Clients should use AssetLoader and ResourceLoader to load an asset before - * passing it in. + * The viewer does not claim ownership over the asset or its entities. Clients should use + * AssetLoader and ResourceLoader to load an asset before passing it in. * * @param asset The asset to view. * @param scale Adds a transform to the root to fit the asset into a unit cube at the origin. */ - void setAsset(FilamentAsset* asset, bool scale); + void populateScene(FilamentAsset* asset, bool scale); /** * Removes the current asset from the viewer. @@ -257,7 +256,7 @@ SimpleViewer::~SimpleViewer() { mEngine->destroy(mSunlight); } -void SimpleViewer::setAsset(FilamentAsset* asset, bool scale) { +void SimpleViewer::populateScene(FilamentAsset* asset, bool scale) { if (mAsset == asset) { while (utils::Entity e = mAsset->popRenderable()) { mScene->addEntity(e); diff --git a/libs/gltfio/src/DependencyGraph.cpp b/libs/gltfio/src/DependencyGraph.cpp index 4cb8c03c1b..3997c66ab5 100644 --- a/libs/gltfio/src/DependencyGraph.cpp +++ b/libs/gltfio/src/DependencyGraph.cpp @@ -59,7 +59,7 @@ void DependencyGraph::addEdge(Texture* texture, MaterialInstance* material, cons void DependencyGraph::markAsReady(Texture* texture) { assert(texture && mFinalized); - mTextures.at(texture)->ready = true; + mTextureNodes.at(texture)->ready = true; // Iterate over the materials associated with this texture to check if any have become ready. // This is O(n2) but the inner loop is always small. @@ -94,10 +94,10 @@ void DependencyGraph::markAsReady(MaterialInstance* material) { } } -DependencyGraph::TextureStatus* DependencyGraph::getStatus(Texture* texture) { - auto iter = mTextures.find(texture); - if (iter == mTextures.end()) { - TextureStatus* status = (mTextures[texture] = std::make_unique()).get(); +DependencyGraph::TextureNode* DependencyGraph::getStatus(Texture* texture) { + auto iter = mTextureNodes.find(texture); + if (iter == mTextureNodes.end()) { + TextureNode* status = (mTextureNodes[texture] = std::make_unique()).get(); *status = {texture, false}; return status; } diff --git a/libs/gltfio/src/DependencyGraph.h b/libs/gltfio/src/DependencyGraph.h index 1f310dee05..d1c750f55d 100644 --- a/libs/gltfio/src/DependencyGraph.h +++ b/libs/gltfio/src/DependencyGraph.h @@ -43,16 +43,16 @@ namespace gltfio { * One graph corresponds to a single glTF asset. The graph only contains weak references, it does * not have ownership over any Filament objects. Here's an example: * - * Entity Entity Entity Entity - * | / \ | / - * | / \ | / - * Material Material Material - * / | \ | - * / | \ | - * Param Param Param Param - * \ / \ / - * \ / \ / - * Texture Texture + * Entity Entity Entity Entity + * | / \ | / + * | / \ | / + * Material Material Material + * / | \ | + * / | \ | + * Param Param Param Param + * \ / | | + * \ / | | + * Texture Texture Texture * * Note that the left-most entity in the above graph has no textures, so it becomes ready as soon as * finalize is called. @@ -77,28 +77,34 @@ public: void markAsReady(filament::Texture* texture); private: - struct TextureStatus { + struct TextureNode { filament::Texture* texture; bool ready; }; - struct MaterialStatus { - tsl::robin_map params; + struct MaterialNode { + tsl::robin_map params; }; - struct EntityStatus { + struct EntityNode { tsl::robin_set materials; size_t numReadyMaterials = 0; }; void markAsReady(Material* material); - TextureStatus* getStatus(filament::Texture* texture); + TextureNode* getStatus(filament::Texture* texture); - tsl::robin_map mEntityToMaterial; + // The following maps contain the directed edges in the graph. + tsl::robin_map mEntityToMaterial; tsl::robin_map> mMaterialToEntity; - tsl::robin_map mMaterialToTexture; + tsl::robin_map mMaterialToTexture; tsl::robin_map> mTextureToMaterial; - tsl::robin_map> mTextures; + + // Each texture (and its readiness flag) can be referenced from multiple nodes, so we own + // a collection of wrapper objects in the following map. This uses std::unique_ptr to allow + // nodes to refer to a texture wrapper using a stable weak pointer. + tsl::robin_map> mTextureNodes; + std::queue mReadyRenderables; bool mFinalized = false; }; diff --git a/samples/gltf_baker.cpp b/samples/gltf_baker.cpp index f25881b71d..6e0fe7c4c2 100644 --- a/samples/gltf_baker.cpp +++ b/samples/gltf_baker.cpp @@ -332,7 +332,7 @@ static void updateViewerMesh(BakerApp& app) { app.viewerAsset->getAnimator(); // Remove old renderables and add new renderables to the scene. - app.viewer->setAsset(app.viewerAsset, !app.viewerActualSize); + app.viewer->populateScene(app.viewerAsset, !app.viewerActualSize); // Destory old Filament entities. app.loader->destroyAsset(previousViewerAsset); diff --git a/samples/gltf_viewer.cpp b/samples/gltf_viewer.cpp index 75998336e9..33db7468de 100644 --- a/samples/gltf_viewer.cpp +++ b/samples/gltf_viewer.cpp @@ -261,7 +261,7 @@ int main(int argc, char** argv) { app.resourceLoader->asyncUpdateLoad(); // Add renderables to the scene as they become ready. - app.viewer->setAsset(app.asset, !app.actualSize); + app.viewer->populateScene(app.asset, !app.actualSize); app.viewer->applyAnimation(now); };