This project is designed to be used with the NVIDIA Omniverse kit-app-template. Using the kit-app-template together with the provided ./kit-app-source/source you can create a streaming Kit application that works together with the provided ./web-app client. If you use the kit-app-template, you agree you have read the NVIDIA Software License Agreement (available at https://www.nvidia.com/en-us/agreements/enterprise-software/nvidia-software-license-agreement/) and Product-Specific Terms for NVIDIA Omniverse (available at https://www.nvidia.com/en-us/agreements/enterprise-software/product-specific-terms-for-omniverse/) and agree to their terms. If you do not have the authority to enter into the License Agreement and/or do not accept the License Agreement terms and conditions, you should not register to use or use the kit-app-template.
This repository provides sample code for creating the applications needed for a Omniverse Kit App Streaming solution. In such a solution, the Kit app is the application that runs on a remote server and the client/web-app is the application that displays the streamed Kit app.
git lfs --version
If the command returns a version number, Git LFS is installed correctly. If not, you will need to install Git LFS. You can download and install it from the official website here.
- kit-app-template using
Kit SDK 106.4
or more recent. Please refer to the kit-app-template project prerequisites as well. The code in ./kit-app-source/source was developed to work withKit SDK 106.4
.
- Node.js installation (https://nodejs.org/en/download).
- Chromium browser.
-
Clone the https://github.com/NVIDIA-Omniverse/kit-app-template repo. The following instructions assume an un-modified kit-app-template project.
-
Copy the ./kit-app-source/source directory in this project into the root directory of the cloned
kit-app-template
. -
Enable the
kit-app-template
repo tools to build the source by adding these lines to premake5.lua:
-- Apps: for each app generate batch files and a project based on kit files (e.g. my_name.my_app.kit)
define_app("msft.usd_viewer.kit")
define_app("msft.usd_viewer_streaming.kit")
- Add this line to kit_args.txt.
"--/app/auto_load_usd=${USD_PATH}"
- Enable precaching of the Kit app by replacing the
[repo_precache_exts]
section repo.toml with this:
[repo_precache_exts]
# Apps to run and precache
apps = [
"${root}/source/apps/msft.usd_viewer.kit",
"${root}/source/apps/msft.usd_viewer_streaming.kit",
]
- Refer to kit-app-template instructions to build the project. For
kit-app-template
based on Kit SDK 106.4, open a terminal in the root of the project and execute:
./repo.sh build
This completes the setup for the Kit app. You now have a built application that can be launched. Let's continue with the web app.
-
Open a terminal in ./web-app.
-
Install dependencies:
npm install
If there is an error when running npm install
:
- Delete ./web-app/node_modules and ./web-app/package-lock.json.
- Run
npm install
again. - Run
npm run build
to create a distribution.
The web app is now ready to be launched locally or deployed.
Pushing a container to the Omniverse App Streaming deployment and testing functionality can be time consuming. You can easily run the Kit and web app locally for quick iteration.
- Launch the web app by opening a terminal in ./web-app and run
npm run dev
.- Terminal displays a localhost URL such as localhost:5173. Open the URL in a Chromium browser.
- Enter
127.0.0.1
in theServer
field and clickStart Local Server
. The web app is now trying to connect to a Kit app running locally.
-
Promptly, launch the Kit app by opening a terminal in the root of
kit-app-template
and run./repo.sh launch
.- When prompted, select the
msft.usd_viewer_streaming.kit
file.
- When prompted, select the
-
You can now see the Kit app streamed into the web app. The Kit app may be just a black rectangle because we didn't load a file.
-
Click the
Set Asset 1 URL
orSet Asset 2 URL
to send a message from the web app to the Kit app with a request to load a file.
Note: You can launch the Kit app with an argument to load a file using ./repo.sh launch -- --/app/auto_load_usd="\${app}/../samples/stage01.usd"
.
Additional information on running solution locally can be found in https://docs.omniverse.nvidia.com/embedded-web-viewer/latest/create/run-the-solution.html documentation.
- Follow the instructions in above Kit App Setup section.
- For
kit-app-template
based on Kit SDK 106.4, open a terminal in the root of the project and execute:- When prompted, select the
msft.usd_viewer_streaming.kit
file.
- When prompted, select the
./repo.sh package --container
- List containers:
docker image list
- Use
docker tag
anddocker push
commands to push the appropriately named container to a registry of your choosing.
- Launch the web app by opening a terminal in ./web-app and run
npm run dev
. - Terminal displays a localhost URL such as localhost:5173. Open the URL in a Chromium browser.
- Enter the URL for the Omniverse App Streaming
Streaming
Service in theService
field. - Click the
Start Service
button.
Requesting a stream can take some time - especially if a new container needs to be pulled by the service. Have patience and monitor the browser console for progress. There can be errors while the web app attempts to connect to a running Kit app container.
The Debug Panel provides controls for modifying and viewing the state variables. It also provides a listing of active sessions and the
ability to end them. The panel can be toggled with CTRL+M
. To understand the code a developer should use this interface and follow
the path of execution.
Use either the Service
or Server
controls to start a stream. Do not use both together. The Service
control
requests a remote session while the Server
enables local streaming.
The Assets
buttons shows how to send a request to load a USD file. The first two makes use of the assets bundled
with the Kit application. Those assets are included in the Kit container. The third button executes a function that
sends a request to load a file using SAS token. You'll need to edit the function variables to make this work.
The Selection
buttons assume that one of the two bundled files are loaded. The files contain 4 USD Prims that
have been tagged with asset_id
attributes with the values cube
, sphere
, cone
, and group
. Clicking a button
will toggle the given asset_id
to be included in the selection list and a message will be sent to the Kit app to
change the current selection.
The Asset State
buttons also assumes that one of the two bundled files are loaded. These buttons send a request
to change the Kit selection group for a given prim: nominal
applies default USD Prim rendering, warning
and fault
provides
different emphasis of the USD Prim rendering.
This section allows you to inspect the current state variable values. For example, if you load one of the two bundled files
and select the cube prim in the viewport - not using the above mentioned buttons - you can see how the assetIds
in the Selection
group updates to list the cube. This is because Kit sends a message to the web app about the selection change and thus
the state is updated.
Here you can click the Get Sessions
button to list the active sessions. You can use the buttons to delete them one by one or all of them.
Note that one of them could be a session you are currently using.
As mentioned in above Run Web App Locally Against Omniverse App Streaming Service,
a session can be started using the Service
field and Start Session
button.
Clicking the Start Session
button executes:
dispatch(setURL(`[some URL]`));
dispatch(setService({ address: addressValue, desiredState: 'connected' }));
The above does two things. First, it sets the UsdStorageState.url
state to the given URL. That by itself
does not send a request to the a streamed Kit application because we have not connected yet. Second,
it sets the ServiceState.sessionService
state and this triggers the ServiceComponent
to request
a streaming session.
Getting an active streaming session requires a number of steps to happen:
- Request the service.
ServiceComponent
makes use of thecreateStreamingSession
API. The URL mentioned above is passed as an argument for the Kit app to load a stage.- The request causes the remote service to pull and start a container.
- The web app polls the service using
getStreamingSessionInfo
until it receives information about an active stream. - Once the
ServiceComponent
receives information about an active stream it sets theAppStreamState.remoteStream
state. - A change in
AppStreamState.remoteStream
state triggersAppStreamComponent
to connect to the stream (see usage ofAppStreamer.connect
usage). - Connecting to the remotely running container is a series of connection attempts (see usage of
maxReconnects
usage for number of attempts). - Once connected the web client will display the streamed application.
Executing setURL
updates the UsdStorageState.url
state and causes the USDStorageComponent
to send a request to the Kit app for opening a file.
The Kit msft.usd_viewer.messaging
handles loading of files in stage_loading.py
.
The streamed viewport is interactive. Mouse events and camera navigation is automatically sent to the streamed application.
A USD Stage contains USD Prims. Each Prim has can be identified by a path. A solution could be created around USD paths but
this creates restraints around USD authoring because paths would not be allowed to change unless the web app is also updated.
Instead, this sample makes use of asset_ids
. Relevant USD Prims are expected to have an asset_id
attribute. Selection and
"Status" changes can be communicated about using the asset_id
instead of Prim paths.
Selection changes in the USD Stage can happen two ways: by selecting something in the viewport or by sending a message to select something.
Viewport selection is automatically handled. The streamed Kit app will send a message to the web app which updates the SelectionState.assetIds
state.
Likewise, the web app can change the SelectionState.assetIds
state and cause the SelectionComponent
to send a message requesting a selection change to the Kit app.
The Kit msft.usd_viewer.messaging
handles selection changes in stage_management.py
.
Changes in StatusState.assetId
and StatusState.assetStatus
causes the StatusComponent
to send a message to the Kit app to change the status of an asset.
The Kit msft.usd_viewer.messaging
handles the status in stage_status.py
.
Clicking the End Session
button executes:
dispatch(setService({ address: addressValue, desiredState: 'destroyed' }));
This updates the ServiceState.sessionService
which triggers AppStreamComponent
to terminate the stream via AppStreamer.terminate()
and the ServiceComponent
to request the service to destroy the current session via destroyStreamingSession
API.
Location: ./kit-app-source/source/apps.
File | Description |
---|---|
msft.usd_viewer.kit | Base application providing an RTX 3D viewport. |
msft.usd_viewer_streaming.kit | Extends msft.usd_viewer.kit by adding streaming and messaging support. |
Location: ./kit-app-source/source/extensions/msft.usd_viewer.setup.
Feature | Description |
---|---|
Auto loading | Supports application to be launched with --/app/auto_load_usd argument. When running within a deployment the container is passed this argument. |
Sample files | Two small sample USD files are included. |
Layout | Sets up the viewport-only application layout. |
Location: ./kit-app-source/source/extensions/msft.usd_viewer.messaging.
Feature | Description |
---|---|
Loading | Enables a client to request loading a stage. |
Stage Management | Allows changing selection change per request. Informs client of selection changes when user interacts in viewport. |
Asset Status | Enables a client to indicate a status for a USD Prim. Makes use of selection groups to apply special rendering. |
File | Description |
---|---|
./web-app/index.html | Top level html. Uses ./web-app/src/main.tsx |
./web-app/src/main.tsx | Makes use of various components. The critical one is <App/> - other are optional. |
./web-app/src/App.tsx | Makes use of required components described below. |
Location: ./web-app/src/state.
State is presented using Redux. These files presents the state and allow other components to change it.
File | Description |
---|---|
store.ts | Provides the Redux reducers. |
appStreamSlice.ts | server state for local streaming.remoteServer for remote stream.kitState indicates the responsiveness of the streamed Kit application. |
selectionSlice.ts | assetIds state for selected assets.selectionChangeOrigin is used to avoid loops in selection changes. |
serviceSlice.ts | sessionService state for controlling what service to use to and whether to create or destroy a service.appId , version , and profile needs to be set to match the container to launch when requesting a stream session.sessionId is the identifier of a current session and is provided by service.status is the status code for when polling service for a session. |
statusSlice.ts | assetId is the identifier to change the status for.assetStatus is the status for a given asset to send to the streamed Kit application. |
usdStorageSlice.ts | url is the most recently requested asset to load.loadingState indicates current activity.loadedURL is the most recently loaded asset. |
Location: ./web-app/src/components.
The components react to state changes and controls some of the states as well. They provide a streamed Omniverse 3D viewport and manages the communication with it.
File | Description |
---|---|
AppStreamComponent.tsx | Provides a streamed Omniverse 3D viewport. |
SelectionComponent.ts | Sends messages to streamed Omniverse 3D viewport to change selection. |
ServiceComponent.ts | Communicates with App Streaming service to create and destroy Omniverse 3D viewport sessions. Supports passing a USD URL to load as part of container startup. |
StatusComponent.ts | Sends messages to streamed Omniverse 3D viewport to change asset status. |
USDStorageComponent.ts | Sends messages to streamed Omniverse 3D viewport to load a stage. |
Location: ./web-app/src/service.
These files provide API for connecting to the Streaming and the Application service. In this implementation, only the Streaming service is used.
File | Description |
---|---|
EndPoint.tsx | Provides the main API for communicating with the service. Other files supports this API. |
Location: ./web-app/src/debug.
The debug code provides sample code for controlling and inspecting the state. This code could be replaced by other code and the solution would still work.
File | Description |
---|---|
Controls.tsx | User interface elements that modifies the state. |
SessionManagement.tsx | Supports listing sessions and destroying them. |
State.tsx | Displays state values. |