Client Library and Live Overview

Introduced in 200.0

The Connect Samples version 200.0 includes a large update to the Omniverse Client Library version 2. This change impacts Connectors in these ways:

  • Omniverse dependencies are retrieved differently

  • The USD Resolver may need to be initialized separately

  • API changes

  • Live sync changes

  • USD version changes

The biggest changes are centered around live sync and USD versions. First, live sync no longer works on .usd files, but is now restricted only to .live files, which we’ll refer to as .live layers. This change to using .live layers allows Omniverse to start live sessions without changing the underlying data. Clients will typically use USD layer composition with the edit target set to the .live layer to enable live synchronization in a USD stage. Note: .live layers are presented to clients as USD layers.

More USD library versions are now supported due to changes in the Client Library and USD Resolver plugin because they can now compile against stock USD.

See the Omniverse Live Workflow Documentation for more information on the UI/UX for implementing and using Live Sessions in USD Composer and other clients.

See the Omniverse Live Workflow Developer FAQ for more information on the immediate changes (also described in some detail below).

Build Changes from Client Library 1.x

  • The Omniverse USD Resolver plugin is now separated from the Client Library, so it adds build dependencies to Connectors.

    • There is a very simple checkpoint API in the resolver plugin that Connectors will probably want to include, so adding the resolver as a build dependency is a new step.

  • The Client Library no longer depends on USD (this enables us to provide more USD versions in the future)

  • The Connect Sample has a build script that “double fetches” using the Packman dependency system.

    • First it grabs the correct Omniverse USD Resolver plugin which contains the USD library dependency and the Client Library dependency locations

    • These are then fetched and land here:

      • _build/target-deps/omni_usd_resolver

      • _build/target-deps/usd

      • _build/target-deps/omni_client_library

Initialization Changes

  • Because the USD Resolver plugin is no longer bundled with the Client Library it needs to be either copied to the correct folder for your application or initialized wherever you decide to use it.

  • The Connect Samples copy the USD Resolver files into the correct place so it is automatically initialized, but we made an example for initializing the resolver plugin anyway in liveSession.cpp. For more information on explicitly initializing the plugin, see the resolver docs in the “Initializing” section.

API Changes

  • All of the different OmniClient*.h files with interfaces required by a client are now combined into a single OmniClient.h file.

  • The application no longer has a “live mode” controllable by the client library API. If a developer is editing a layer with a .live file extension and uses omniClientLiveProcess() then all changes are automatically sent and received.

  • The resolver can now be used to set a checkpoint message because every file save generates checkpoints (labeled or not): omniUsdResolverSetCheckpointMessage()

Live Changes

Client and Resolver Changes

  • The live transfer of data between clients and Omniverse servers has been revamped with these goals in mind:

    • Support the full USD feature set. Anything that can be done in USD is supported with live layers.

    • Multiple simultaneous editors. This includes being able to edit the same prims, and even the same attributes, at the exact same time.

    • High performance. The power of live layers comes from their interactive speeds. However, performance must not come at the cost of correctness.

    • Read more about the intricacies in the USD Resolver technical overview documentation

  • Only .live files/layers resident on an Omniverse server will replicate data

  • omniClientLiveProcess() is used to both send and receive changes to and from the Omniverse server. It is no longer required to save the .live layer using the USD Save API.

Live Session implications - Non-Destructive Live Session Workflow

To go along with only replicating data through .live layers the Omniverse team is formalizing a scheme for Omniverse applications and Connectors to have robust live editing sessions.

The idea is that when a Connector or content creation tool generates USD data (stages, props, etc), we want creators to be able to live-collaborate without unintentionally destroying or modifying that data.

  • Live stage composition

    • The .live layer is inserted, by each participating client, into the Session Layer. This is done for two reasons:

      • This avoids altering the original USD stage

      • All changes made in the .live layer will take authority over data in the base, or root USD stage.

      • Example:

        Live_Stage.usd
        --------------
        Session Layer
        |_ root.live (layer)
          |_ (overs replicated by Omniverse)
        Root Layer
          |_ /World
            |_ (Prims with overs in root.live)
        
  • Live stage file and folder structure

    • The .live layer files need to live somewhere on the Omniverse server so we established a common location for them.

    • .live folder - All live session files are stored in a folder called “.live”

      • usd_root_stage.live folder - a folder is created for each root USD file since a live session can only apply to one particular USD file

        • session_name.live - each session gets its own folder to store the session files

    • Session files - there are three files that exist for each session

      • root.live - the .live layer where overs and new defs are stored for the session

      • __session__.channel - the channel file used by clients to send and receive Omniverse channel messages with other clients (peer presence, merge intentions, etc.)

      • __session__.toml - a configuration file for the live session

    • Inside the same folder where the USD root file usd_root_stage.usd being live-edited in a session called session_name, a folder structure like this would exist:

      • ./.live/usd_root_stage.live/session_name.live/...

  • Live session configuration file: __session__.toml

    • It contains these key/value pairs:

      * version = "1.0"
      * user_name = "owner_user_name"
      * mode = "default"  ("auto_authoring", "root_authoring", "project_authoring")
      * stage_url = "omniverse://server/path/root_stage.usd"
      * (optional) description = "A description of the session purpose"
      
    • When a client creates a new session, this file should be created with the above key/value pairs defined. The user_name value should be the owner’s username for the URL defined in stage_url.

  • Live session channel communication

    • An Omniverse Channel is used to communicate peer presence and merge status in the live session between clients. Clients broadcast JSON messages in this format:

Omniverse Channel JSON Format

Key

Value

Type

Comments

version

3.0

String

Message version. 3.0 is the version defined by Kit in this release. The version is composed as pattern [major].[minor]. If the major version is upgraded it is no longer backwards compatible. An increase of minor versions will still be backwards compatible and possibly add new keys. Clients with older major versions should not join sessions with a newer major version.

from_user_name

Any String

String

User name. Since the Omniverse channel message only includes the user ID this field helps to provide a user-friendly login name.

app

Any String

String

The application name of the connected client (USD Composer, C++ Connect Sample, Maya, etc.).

message_type

  • JOIN

  • GET_USERS

  • HELLO

  • LEFT

  • MESSAGE

String

The message type. It supports these messages types:

  • JOIN - Sent when a new user joins. Nucleus channel will send out the join message after the user is firstly connected to the channel, however, it only includes the user id but not the readable user name. We extend it with a customized message. So connectors should send out this when it’s joined into a session.

  • HELLO - The response to JOIN or GET_USERS messages, as Nucleus channel is stateless, so any new users that join into the channel do not know who are in that channel already. So connectors should send out this when it receives any JOIN message.

  • GET_USERS - When a client receives a GET_USERS message, it should respond to a HELLO message. Instead of JOIN, GET_USERS means the client wants to know other clients in the session but has not joined in this session yet. Clients receiving GET_USERS messages are recommended not to treat this client as a joined user in this session.

  • LEFT - Sent when the user quits the live session.

  • MESSAGE - Customized message based on the application. Application can design the protocol with a content field and parse the content field for details.

content

Any dict

Dict

A dictionary that includes all customized protocols based on the application

  • Here are examples in JSON format based on the message specification:

    {"version": "3.0", "from_user_name": "omniverse", "message_type": "JOIN", "content": {}}
    {"version": "3.0", "from_user_name": "omniverse", "message_type": "LEFT", "content": {}}
    {"version": "3.0", "from_user_name": "omniverse", "message_type": "HELLO", "content": {}}
    
  • Customized Messages for Managing the Session Merge Process

    • At the end of a live session the session owner may merge live changes into the root or new layers. To notify other users of this event customized messages are broadcast with message_type = MESSAGE. The contents of the message are contained in the payload of the content field as a dictionary. For session management, the content key is __SESSION_MANAGEMENT__ with the value being another dictionary to describe the details. This table describes the session management messages:

Merge Session Message JSON Format

Key

Value

Type

Comments

version

1.0

String

Message version. 1.0 is the version defined the current live session protocol.

message

  • MERGE_STARTED

  • MERGE_FINISHED

String

  • MERGE_STARTED - Sent when the owner starts to merge the live changes (possibly by opening the merge dialog). When a client receives this message it should disable any further changes to the .live layer and pop up a modal dialog indicating this.

  • MERGE_FINISHED - Sent when the merge is complete

  • An example of a MERGE_STARTED message sent in JSON:

    {
        "version": "3.0",
        "from_user_name": "omniverse",
        "message_type": "MESSAGE",
        "content":
        {
            "__SESSION_MANAGEMENT__":
            {
                "version": "1.0",
                "message": "MERGE_STARTED"
            }
        }
    }
    
  • Disabling and Deleting Prims

    • USD prims that are defined in the root layer cannot be deleted with an “over”, it’s not possible. If the client intends to delete a prim from the root layer it must use UsdPrim::SetActive(false) to deactivate the prim. This will effectively remove the prim from the viewport by setting its “active” metadata to false. This doesn’t remove the prim or any of its children from the stage file, but default stage traversals will no longer see it. This USD glossary entry for Active/Inactive discusses “non destructive and reversible prim deletion”.

  • Merging live session changes

    • When a session is complete and the owner wants to keep the changes from the session, they can choose to merge them into the root stage.

      • default, or root_authoring mode: in this case, the .live and root layers are flattened in a temporary stage, then copied into the stage’s root layer.

      • auto_authoring mode: each live layer is merged into its respective root sublayer (currently this is experimental and only USD Composer can support such a session)

      • See the Live Workflow FAQ for more information about these modes.

    • The specific “merge and end session” process works like this:

      1. Verify that the current connected user is actually the “owner” of the session

      2. Send a MERGE_STARTED channel message

      3. At this point other clients will disconnect from the live session to prevent any unwanted changes

      4. Create a non-forced checkpoint on the live layer

      5. Create a non-forced checkpoint on the root layer

      6. Merge the live changes to the root layer

      7. Create a checkpoint on the root layer while saving it

      8. Clear the live layer changes

      9. Remove the .live layer from the session layer (so that the open stage is still valid for editing in the client)

      10. Send a MERGE_FINISHED channel message

.live Layers Without Sessions

Some clients may choose to forgo the Live Session workflow and simply use .live sublayers in their layer composition. A .live layer acts just like USD to the client, so when the client sets the edit target to Original_Stage_Edits.live all changes will be replicated through Nucleus. This is assuming that omniClientLiveProcess() is being called on all clients (USD Composer automatically does this). This doesn’t require a “live session” to be active. Note, the HelloWorld sample still allows you to open a .live file and edit it, demonstrating this point.

Example:

Original_Stage.usd
--------------
|_ Original_Stage_Edits.live (layer)
    |_ (overs replicated by Omniverse)
|_ Original_Stage_Base.usd (layer)
    |_ /World
    |_ (Prims with overs in Original_Stage_Edits.live)

Client and Resolver Documentation