From 6ee29a1c863792c752f7f710b6b5e69722a780be Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 12 Feb 2024 11:09:37 -0500 Subject: [PATCH 1/6] Wait for loading tiles when capturing movies --- .vscode/cesium-omniverse-linux.code-workspace | 1 + .vscode/cesium-omniverse-windows.code-workspace | 1 + exts/cesium.omniverse/cesium/omniverse/extension.py | 11 ++++++++++- exts/cesium.omniverse/config/extension.toml | 1 + include/cesium/omniverse/CesiumOmniverse.h | 6 ++++-- src/bindings/PythonBindings.cpp | 4 ++-- src/core/include/cesium/omniverse/AssetRegistry.h | 2 +- src/core/include/cesium/omniverse/Context.h | 2 +- src/core/include/cesium/omniverse/OmniTileset.h | 4 ++-- src/core/src/AssetRegistry.cpp | 4 ++-- src/core/src/Context.cpp | 4 ++-- src/core/src/OmniTileset.cpp | 12 ++++++++---- src/public/CesiumOmniverse.cpp | 4 ++-- 13 files changed, 37 insertions(+), 19 deletions(-) diff --git a/.vscode/cesium-omniverse-linux.code-workspace b/.vscode/cesium-omniverse-linux.code-workspace index 1124cb54c..3cede43ca 100644 --- a/.vscode/cesium-omniverse-linux.code-workspace +++ b/.vscode/cesium-omniverse-linux.code-workspace @@ -96,6 +96,7 @@ "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.audio.test.usd", "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.autocapture", "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.capture", + "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.capture.viewport", "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.clipboard", "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.collaboration.channel_manager", "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.collaboration.presence_layer", diff --git a/.vscode/cesium-omniverse-windows.code-workspace b/.vscode/cesium-omniverse-windows.code-workspace index d7eac20fa..677cec7d2 100644 --- a/.vscode/cesium-omniverse-windows.code-workspace +++ b/.vscode/cesium-omniverse-windows.code-workspace @@ -96,6 +96,7 @@ "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.audiodeviceenum", "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.autocapture", "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.capture", + "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.capture.viewport", "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.clipboard", "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.collaboration.channel_manager", "${workspaceFolder}/extern/nvidia/_build/target-deps/kit-sdk/exts/omni.kit.collaboration.presence_layer", diff --git a/exts/cesium.omniverse/cesium/omniverse/extension.py b/exts/cesium.omniverse/cesium/omniverse/extension.py index 79dc7f40a..6304ffa8f 100644 --- a/exts/cesium.omniverse/cesium/omniverse/extension.py +++ b/exts/cesium.omniverse/cesium/omniverse/extension.py @@ -32,6 +32,7 @@ from typing import List, Optional, Callable from .ui.credits_viewport_controller import CreditsViewportController from cesium.usd.plugins.CesiumUsdSchemas import Data as CesiumData, IonServer as CesiumIonServer +from omni.kit.capture.viewport import CaptureExtension CESIUM_DATA_PRIM_PATH = "/Cesium" @@ -70,6 +71,7 @@ def __init__(self) -> None: self._logger: logging.Logger = logging.getLogger(__name__) self._menus = [] self._num_credits_viewport_frames: int = 0 + self._capture_instance = None perform_vendor_install() @@ -171,6 +173,8 @@ def on_startup(self): add_raster_overlay_event, self._on_add_raster_overlay_to_tileset ) + self._capture_instance = omni.kit.capture.viewport.CaptureExtension.get_instance() + def on_shutdown(self): self._menus.clear() @@ -235,6 +239,8 @@ def on_shutdown(self): self._add_menu_controller.destroy() self._add_menu_controller = None + self._capture_instance = None + self._destroy_credits_viewport_frames() self._logger.info("CesiumOmniverse shutdown") @@ -261,7 +267,10 @@ def _on_update_frame(self, _): self._setup_credits_viewport_frames() self._num_credits_viewport_frames = len(viewports) - _cesium_omniverse_interface.on_update_frame(viewports) + wait_for_loading_tiles = ( + self._capture_instance.progress.capture_status == omni.kit.capture.viewport.CaptureStatus.CAPTURING + ) + _cesium_omniverse_interface.on_update_frame(viewports, wait_for_loading_tiles) def _on_stage_event(self, event): if _cesium_omniverse_interface is None: diff --git a/exts/cesium.omniverse/config/extension.toml b/exts/cesium.omniverse/config/extension.toml index 1d05692b3..91d30a244 100644 --- a/exts/cesium.omniverse/config/extension.toml +++ b/exts/cesium.omniverse/config/extension.toml @@ -45,6 +45,7 @@ python = false "omni.kit.viewport.utility" = {} "omni.kit.property.usd" = {} "omni.kit.menu.utils" = {} +"omni.kit.capture.viewport" = {} # Main python module this extension provides, it will be publicly available as "import cesium.omniverse" [[python.module]] diff --git a/include/cesium/omniverse/CesiumOmniverse.h b/include/cesium/omniverse/CesiumOmniverse.h index 6c224d962..210745c33 100644 --- a/include/cesium/omniverse/CesiumOmniverse.h +++ b/include/cesium/omniverse/CesiumOmniverse.h @@ -49,9 +49,11 @@ class ICesiumOmniverseInterface { /** * @brief Updates all tilesets this frame. * - * @param viewports A list of viewports. + * @param viewports The viewports. + * @param count The number of viewports. + * @param waitForLoadingTiles Whether to wait for all tiles to load before continuing. */ - virtual void onUpdateFrame(const ViewportApi* viewports, uint64_t count) noexcept = 0; + virtual void onUpdateFrame(const ViewportApi* viewports, uint64_t count, bool waitForLoadingTiles) noexcept = 0; /** * @brief Updates the reference to the USD stage for the C++ layer. diff --git a/src/bindings/PythonBindings.cpp b/src/bindings/PythonBindings.cpp index 36698f748..074ce24db 100644 --- a/src/bindings/PythonBindings.cpp +++ b/src/bindings/PythonBindings.cpp @@ -48,8 +48,8 @@ PYBIND11_MODULE(CesiumOmniversePythonBindings, m) { .def("on_startup", &ICesiumOmniverseInterface::onStartup) .def("on_shutdown", &ICesiumOmniverseInterface::onShutdown) .def("reload_tileset", &ICesiumOmniverseInterface::reloadTileset) - .def("on_update_frame", [](ICesiumOmniverseInterface& interface, const std::vector& viewports) { - return interface.onUpdateFrame(reinterpret_cast(viewports.data()), viewports.size()); + .def("on_update_frame", [](ICesiumOmniverseInterface& interface, const std::vector& viewports, bool waitForLoadingTiles) { + return interface.onUpdateFrame(reinterpret_cast(viewports.data()), viewports.size(), waitForLoadingTiles); }) .def("on_stage_change", &ICesiumOmniverseInterface::onUsdStageChanged) .def("connect_to_ion", &ICesiumOmniverseInterface::connectToIon) diff --git a/src/core/include/cesium/omniverse/AssetRegistry.h b/src/core/include/cesium/omniverse/AssetRegistry.h index 848bec402..12d4ac494 100644 --- a/src/core/include/cesium/omniverse/AssetRegistry.h +++ b/src/core/include/cesium/omniverse/AssetRegistry.h @@ -41,7 +41,7 @@ class AssetRegistry { AssetRegistry(AssetRegistry&&) noexcept = delete; AssetRegistry& operator=(AssetRegistry&&) noexcept = delete; - void onUpdateFrame(const gsl::span& viewports); + void onUpdateFrame(const gsl::span& viewports, bool waitForLoadingTiles); OmniData& addData(const pxr::SdfPath& path); void removeData(const pxr::SdfPath& path); diff --git a/src/core/include/cesium/omniverse/Context.h b/src/core/include/cesium/omniverse/Context.h index 23ac9bc56..92178870a 100644 --- a/src/core/include/cesium/omniverse/Context.h +++ b/src/core/include/cesium/omniverse/Context.h @@ -60,7 +60,7 @@ class Context { void clearStage(); void reloadStage(); - void onUpdateFrame(const gsl::span& viewports); + void onUpdateFrame(const gsl::span& viewports, bool waitForLoadingTiles); void onUsdStageChanged(int64_t stageId); [[nodiscard]] const pxr::UsdStageWeakPtr& getUsdStage() const; diff --git a/src/core/include/cesium/omniverse/OmniTileset.h b/src/core/include/cesium/omniverse/OmniTileset.h index 80bf64f1b..1e8fc25ba 100644 --- a/src/core/include/cesium/omniverse/OmniTileset.h +++ b/src/core/include/cesium/omniverse/OmniTileset.h @@ -87,11 +87,11 @@ class OmniTileset { void updateShaderInput(const pxr::SdfPath& shaderPath, const pxr::TfToken& attributeName); void updateDisplayColorAndOpacity(); - void onUpdateFrame(const gsl::span& viewports); + void onUpdateFrame(const gsl::span& viewports, bool waitForLoadingTiles); private: void updateTransform(); - void updateView(const gsl::span& viewports); + void updateView(const gsl::span& viewports, bool waitForLoadingTiles); [[nodiscard]] bool updateExtent(); void updateLoadStatus(); diff --git a/src/core/src/AssetRegistry.cpp b/src/core/src/AssetRegistry.cpp index 8c91cdc0a..2fe2b0351 100644 --- a/src/core/src/AssetRegistry.cpp +++ b/src/core/src/AssetRegistry.cpp @@ -20,9 +20,9 @@ AssetRegistry::AssetRegistry(Context* pContext) AssetRegistry::~AssetRegistry() = default; -void AssetRegistry::onUpdateFrame(const gsl::span& viewports) { +void AssetRegistry::onUpdateFrame(const gsl::span& viewports, bool waitForLoadingTiles) { for (const auto& pTileset : _tilesets) { - pTileset->onUpdateFrame(viewports); + pTileset->onUpdateFrame(viewports, waitForLoadingTiles); } } diff --git a/src/core/src/Context.cpp b/src/core/src/Context.cpp index 2375380dd..4c9ec561b 100644 --- a/src/core/src/Context.cpp +++ b/src/core/src/Context.cpp @@ -150,9 +150,9 @@ void Context::reloadStage() { } } -void Context::onUpdateFrame(const gsl::span& viewports) { +void Context::onUpdateFrame(const gsl::span& viewports, bool waitForLoadingTiles) { _pUsdNotificationHandler->onUpdateFrame(); - _pAssetRegistry->onUpdateFrame(viewports); + _pAssetRegistry->onUpdateFrame(viewports, waitForLoadingTiles); _pCesiumIonServerManager->onUpdateFrame(); } diff --git a/src/core/src/OmniTileset.cpp b/src/core/src/OmniTileset.cpp index aecaa6363..ed05bb079 100644 --- a/src/core/src/OmniTileset.cpp +++ b/src/core/src/OmniTileset.cpp @@ -567,7 +567,7 @@ void OmniTileset::updateShaderInput(const pxr::SdfPath& shaderPath, const pxr::T }); } -void OmniTileset::onUpdateFrame(const gsl::span& viewports) { +void OmniTileset::onUpdateFrame(const gsl::span& viewports, bool waitForLoadingTiles) { if (!UsdUtil::primExists(_pContext->getUsdStage(), _path)) { // TfNotice can be slow, and sometimes we get a frame or two before we actually get a chance to react on it. // This guard prevents us from crashing if the prim no longer exists. @@ -575,7 +575,7 @@ void OmniTileset::onUpdateFrame(const gsl::span& viewports) { } updateTransform(); - updateView(viewports); + updateView(viewports, waitForLoadingTiles); if (!_extentSet) { _extentSet = updateExtent(); @@ -604,7 +604,7 @@ void OmniTileset::updateTransform() { } } -void OmniTileset::updateView(const gsl::span& viewports) { +void OmniTileset::updateView(const gsl::span& viewports, bool waitForLoadingTiles) { const auto visible = UsdUtil::isPrimVisible(_pContext->getUsdStage(), _path); if (visible && !getSuspendUpdate()) { @@ -616,7 +616,11 @@ void OmniTileset::updateView(const gsl::span& viewports) { _viewStates.push_back(UsdUtil::computeViewState(*_pContext, georeferencePath, _path, viewport)); } - _pViewUpdateResult = &_pTileset->updateView(_viewStates); + if (waitForLoadingTiles) { + _pViewUpdateResult = &_pTileset->updateViewOffline(_viewStates); + } else { + _pViewUpdateResult = &_pTileset->updateView(_viewStates); + } } if (!_pViewUpdateResult) { diff --git a/src/public/CesiumOmniverse.cpp b/src/public/CesiumOmniverse.cpp index 9a7c709ef..bff2b1ed7 100644 --- a/src/public/CesiumOmniverse.cpp +++ b/src/public/CesiumOmniverse.cpp @@ -41,9 +41,9 @@ class CesiumOmniversePlugin final : public ICesiumOmniverseInterface { } } - void onUpdateFrame(const ViewportApi* viewports, uint64_t count) noexcept override { + void onUpdateFrame(const ViewportApi* viewports, uint64_t count, bool waitForLoadingTiles) noexcept override { const auto span = gsl::span(reinterpret_cast(viewports), count); - _pContext->onUpdateFrame(span); + _pContext->onUpdateFrame(span, waitForLoadingTiles); } void onUsdStageChanged(long stageId) noexcept override { From 155f42fdd208f89e0f4428521128ccdf981346de Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 12 Feb 2024 11:26:38 -0500 Subject: [PATCH 2/6] Fix Python linting --- exts/cesium.omniverse/cesium/omniverse/extension.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exts/cesium.omniverse/cesium/omniverse/extension.py b/exts/cesium.omniverse/cesium/omniverse/extension.py index 6304ffa8f..475f22ac3 100644 --- a/exts/cesium.omniverse/cesium/omniverse/extension.py +++ b/exts/cesium.omniverse/cesium/omniverse/extension.py @@ -173,7 +173,7 @@ def on_startup(self): add_raster_overlay_event, self._on_add_raster_overlay_to_tileset ) - self._capture_instance = omni.kit.capture.viewport.CaptureExtension.get_instance() + self._capture_instance = CaptureExtension.get_instance() def on_shutdown(self): self._menus.clear() From 0762dab93a4cbb93cc18c2770ef167684eb7f72f Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Tue, 13 Feb 2024 11:18:25 -0500 Subject: [PATCH 3/6] Remove unused code --- src/core/src/Context.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/src/Context.cpp b/src/core/src/Context.cpp index 88812132f..8faa65412 100644 --- a/src/core/src/Context.cpp +++ b/src/core/src/Context.cpp @@ -134,8 +134,6 @@ void Context::clearStage() { } void Context::reloadStage() { - const auto defaultIonServerPath = pxr::SdfPath("/CesiumServers/IonOfficial"); - clearStage(); // Populate the asset registry from prims already on the stage From 5c7f5b2729197720e59686521ae5dfa0d3940bc2 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Tue, 13 Feb 2024 11:32:48 -0500 Subject: [PATCH 4/6] Avoid sending USD notification when server doesn't change --- exts/cesium.omniverse/cesium/omniverse/usdUtils/usdUtils.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/exts/cesium.omniverse/cesium/omniverse/usdUtils/usdUtils.py b/exts/cesium.omniverse/cesium/omniverse/usdUtils/usdUtils.py index 0c7a36344..50091fd4d 100644 --- a/exts/cesium.omniverse/cesium/omniverse/usdUtils/usdUtils.py +++ b/exts/cesium.omniverse/cesium/omniverse/usdUtils/usdUtils.py @@ -154,7 +154,11 @@ def get_path_to_current_ion_server() -> Optional[str]: def set_path_to_current_ion_server(path: str) -> None: data = get_or_create_cesium_data() rel = data.GetSelectedIonServerRel() - rel.SetTargets([path]) + + # This check helps avoid sending unnecessary USD notifications + # See https://github.com/CesiumGS/cesium-omniverse/issues/640 + if get_path_to_current_ion_server() != path: + rel.SetTargets([path]) def get_tileset_paths() -> List[str]: From 53a2438fdf061de55226fdf08f9373278f7771c3 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Tue, 13 Feb 2024 11:35:16 -0500 Subject: [PATCH 5/6] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index e9019adde..18d91a472 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ * Fixed crash when updating tilesets shader inputs. * Fixed crash when setting certain `/Cesium` debug options at runtime. * Fixed crash when disabling and re-enabling the extension. +* Fixed a bug where save stage dialog would appear when reloading Fabric stage at startup. ### v0.17.0 - 2024-02-01 From 98b74fb614df1173f4b64bf3049f46b3d916978b Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Tue, 13 Feb 2024 11:42:56 -0500 Subject: [PATCH 6/6] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index e9019adde..11cee6498 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ * Fixed crash when updating tilesets shader inputs. * Fixed crash when setting certain `/Cesium` debug options at runtime. * Fixed crash when disabling and re-enabling the extension. +* The movie capture tool now waits for tilesets to complete loading before it captures a frame. ### v0.17.0 - 2024-02-01