Connect Sample

The stage created by the HelloWorld Sample

Overview

Build your own NVIDIA Omniverse Connector with prebuilt source code samples that use Pixar’s USD and Omniverse Client Library API’s.

Run build.bat to download the USD and Omniverse dependencies, generate the Visual Studio solution file, and build it.

If interested in what dependencies are necessary to build your own Connector, examine either the premake.lua build configuration file or the output project files in the _compiler folder.

Omni CLI

A command line utility to manage files on a Nucleus Server (omnicli.bat).

This program was initially created to exercise most of the Omniverse Client Library API, but has grown to be a useful utility to interact with Nucleus servers. Typing help will produce a menu that shows the many functions available. Among the most useful are the move/copy functions which can transfer data to and from servers.

HelloWorld (C++)

A sample program that creates a USD stage on a Nucleus server (run_sample.bat).

The sample demonstrates how to:

  • connect to an Omniverse server

  • create a USD stage

  • create a polygonal box and add it to the stage

  • upload an MDL material and its textures to an Omniverse server

  • bind an MDL and USD Preview Surface material to the box

  • add a distant and dome light to the stage

  • create Nucleus checkpoints

  • move and rotate the box with live updates

  • disconnect from an Omniverse server

  • print verbose Omniverse logs

  • open an existing stage and find a mesh to do live edits

HelloWorld (Python)

A sample program with the same functionality of the C++ HelloWorld sample written in Python (run_py_sample.bat).

Launcher

To find where the Connect Sample is installed, find the Connect Sample under the Library:Connectors tab, click the hamburger icon and select “Settings”:

Go to the Settings from the hamburger menu button

Clicking the folder icon next to the Install Path will open a file browser window to where it is installed:

Click the folder icon to open the install location of the Connect Sample

Configuring MSVC (Advanced)

When prebuild.bat is executed (by itself or through build.bat) a version of the Microsoft Visual Studio Compiler and the Windows 10 SDK are downloaded and referenced by the generated Visual Studio projects. If a user wants the projects to use an installed version of Visual Studio then run configure_win_buildtools.bat first. This script should find vswhere.exe and then use it to discover which MSVC compiler to use. If it does not you can edit the deps/host-deps.packman.xml file’s buildtools source path to the folder on your PC which contains the VC subfolder (normally something like C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools).

Changing the Windows 10 SDK (Advanced)

If a user wants the generated projects to use a different Windows 10 SDK than what is downloaded then the configure_win_buildtools.bat file will automatically search for one using the winsdk.bat Microsoft tool and insert the correct paths into the deps/host-deps.packman.xml file. If the winsdk.bat file doesn’t do what is required, edit these fields in the deps/host-deps.packman.xml file:

  • winsdk

  • winsdk_bin

  • winsdk_include

  • winsdk_lib

Note that an installed Windows SDK will have the actual version in all of these paths, for example include/10.0.17763.0 rather than just include

Creating a Windows USD App from the Omniverse Connect Sample

This section describes how to create a simple application that will open a USD stage located on an Omniverse Nucleus server based on the USD and Omniverse Client Libraries retrieved from the Connect Sample. Once the stage is open it will simply report the stage up-axis, the stage linear units, and list all of the prim node paths.

Dependencies for Omniverse Client Library and USD

Both the Omniverse Client Library and NVIDIA’s modified USD SDK are required, so the first thing to do is to copy them into the project structure of the simple app.

From the Connect Sample root folder, these two folders should be copied (after the dependencies are fetched using either prebuild.bat or build.bat):

  • _build\target-deps\nv_usd

  • _build\target-deps\omni_client_library

Both of these dependencies contain symbolic links, so care must be taken when copying them into the simple app’s folders. robocopy (distributed with Windows 10) does a good job of deep-copying symbolic links. The deps folder will hold the USD and Client Library dependencies for the application. Here are a couple command lines that can be run from within the Connect Sample’s root folder, note that in this case the simple project is located in the X:\tmp\OmniUSDReader directory:

  • robocopy /S _build\target-deps\nv_usd X:\tmp\OmniUSDReader\deps\nv_usd

  • robocopy /S _build\target-deps\omni_client_library X:\tmp\OmniUSDReader\deps\omni_client_library

Project Settings

Because this application uses USD that means it uses Boost and TBB which require libraries, preprocessor definitions, and additional options. Also note that we only provide the 64 bit x64 platform binaries, so don’t try to build for the 32 bit platform in Visual Studio when you generate a new console project (for this example at least).

Linker Settings

Visual Studio Linker Options
  1. Additional Library Directories:
    • Debug
      • deps\nv_usd\debug\lib;deps\omni_client_library\debug

    • Release
      • deps\nv_usd\release\lib;deps\omni_client_library\release

  2. Additional Dependencies:
    • Debug
      • ar.lib;arch.lib;gf.lib;js.lib;kind.lib;pcp.lib;plug.lib;sdf.lib;tf.lib;trace.lib;usd.lib;usdGeom.lib;vt.lib;work.lib;usdShade.lib;usdLux.lib;omniclient.lib;python37.lib;boost_python37-vc141-mt-gd-x64-1_68.lib

    • Release
      • ar.lib;arch.lib;gf.lib;js.lib;kind.lib;pcp.lib;plug.lib;sdf.lib;tf.lib;trace.lib;usd.lib;usdGeom.lib;vt.lib;work.lib;usdShade.lib;usdLux.lib;omniclient.lib;python37.lib;boost_python37-vc141-mt-x64-1_68.lib

    • Note that the boost python library is the only difference between debug and release

C/C++ Compiler Settings

Visual Studio C++ Options
  1. Additional Options (to silence warnings):
    • /wd4244 /wd4305

  2. Additional Include Directories:
    • Debug
      • deps\nv_usd\debug\include;deps\omni_client_library\include

    • Release
      • deps\nv_usd\release\include;deps\omni_client_library\include

  3. Preprocessor Definitions:
    • Debug
      • BOOST_ALL_DYN_LINK;NOMINMAX;TBB_USE_DEBUG=1

    • Release
      • BOOST_ALL_DYN_LINK;NOMINMAX;TBB_USE_DEBUG=0

Post-build Event to Copying Runtime Dependencies

There are a lot of runtime dependencies, to make things easy they are simply copied to the same folder as the output executable. A batch file that runs after the app is built makes this convenient and free of errors.

Visual Studio C++ Options
  1. Post-Build Event:
    • Debug
      • scripts\copy_binary_deps.bat debug $(OutputPath)

    • Release
      • scripts\copy_binary_deps.bat release $(OutputPath)

The copy_binary_deps.bat script is run after each build and puts the runtime dependencies in the correct place. It should be copied into the project’s scripts folder:

@echo off
:: copy the USD and OmniClient libs to the $(OutputPath)
:: parameters:
:: 1. debug or release
:: 2. $(OutputPath)

set BUILD_CONFIG=%1
set OUTPUT_PATH=%2
set RC_OPTS=/NP /NJH /NJS /NS /NC /NFL /NDL

echo Copying deps\nv_usd\%BUILD_CONFIG%\lib contents to %OUTPUT_PATH%
robocopy /S deps\nv_usd\%BUILD_CONFIG%\lib %OUTPUT_PATH% %RC_OPTS%

echo Copying deps\omni_client_library\%BUILD_CONFIG% contents to %OUTPUT_PATH%
robocopy /S deps\omni_client_library\%BUILD_CONFIG% %OUTPUT_PATH% %RC_OPTS%

exit /B 0

Simple App Overview

The application performs a few simple things:

  • Expects one argument, the path to a USD stage

    • Acceptable forms:

      • omniverse://localhost/Users/test/helloworld.usd

      • C:\\USD\\helloworld.usd

      • A relative path based on the CWD of the program (helloworld.usd)

    • Initialize Omniverse

      • Set the Omniverse Client log callback

      • Set the Omniverse Client log level

      • Initialize the Omniverse Client library

      • Register an Omniverse Client status callback

    • Open the USD stage

    • Print the stage’s up-axis

    • Print the stage’s linear units, or “meters per unit” setting

    • Traverse the stage prims and print the path of each one

    • Destroy the stage object

    • Shutdown the Omniverse Client library

OmniUSDReader.cpp

Here’s a copy of the simple OmniUSDReader app. The intent is to eventually distribute it with the Connect Sample, but it’s listed here to make it readily available:

/*###############################################################################
#
# Copyright 2021 NVIDIA Corporation
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
###############################################################################*/

/*###############################################################################
#
# The "OmniUSDReader" application performs a few simple things:
#      * Expects one argument, the path to a USD stage
#              * Acceptable forms:
#                      * omniverse://localhost/Users/test/helloworld.usd
#                      * C:\USD\helloworld.usd
#                      * A relative path based on the CWD of the program (helloworld.usd)
#      * Initialize Omniverse
#              * Set the Omniverse Client log callback (using a lambda)
#              * Set the Omniverse Client log level
#              * Initialize the Omniverse Client library
#              * Register an Omniverse Client status callback (using a static function)
#      * Open the USD stage
#      * Print the stage’s up-axis
#      * Print the stage’s linear units, or “meters per unit” setting
#      * Traverse the stage prims and print the path of each one
#      * Destroy the stage object
#      * Shutdown the Omniverse Client library
#
###############################################################################*/

#include <iostream>
#include <iomanip>
#include "OmniClient.h"
#include "pxr/usd/usd/stage.h"
#include "pxr/usd/usd/primRange.h"
#include "pxr/usd/usdGeom/metrics.h"

using namespace pxr;

static void OmniClientConnectionStatusCallbackImpl(void* userData, const char* url, OmniClientConnectionStatus status) noexcept
{
    std::cout << "Connection Status: " << omniClientGetConnectionStatusString(status) << " [" << url << "]" << std::endl;
    if (status == eOmniClientConnectionStatus_ConnectError)
    {
        // We shouldn't just exit here - we should clean up a bit, but we're going to do it anyway
        std::cout << "[ERROR] Failed connection, exiting." << std::endl;
        exit(-1);
    }
}

// Startup Omniverse
static bool startOmniverse()
{
    // Register a function to be called whenever the library wants to print something to a log
    omniClientSetLogCallback(
        [](char const* threadName, char const* component, OmniClientLogLevel level, char const* message)
        {
            std::cout << "[" << omniClientGetLogLevelString(level) << "] " << message << std::endl;
        });

    // The default log level is "Info", set it to "Debug" to see all messages
    omniClientSetLogLevel(eOmniClientLogLevel_Info);

    // Initialize the library and pass it the version constant defined in OmniClient.h
    // This allows the library to verify it was built with a compatible version. It will
    // return false if there is a version mismatch.
    if (!omniClientInitialize(kOmniClientVersion))
    {
        return false;
    }

    omniClientRegisterConnectionStatusCallback(nullptr, OmniClientConnectionStatusCallbackImpl);

    return true;
}

// The program expects one argument, a path to a USD file
int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        std::cout << "Please provide an Omniverse stage URL to read." << std::endl;
        return -1;
    }

    std::cout << "Omniverse USD Stage Traversal: " << argv[1] << std::endl;

    startOmniverse();

    UsdStageRefPtr stage = UsdStage::Open(argv[1]);
    if (!stage)
    {
        std::cout << "Failure to open stage.  Exiting." << std::endl;
        return -2;
    }

    // Print the up-axis
    std::cout << "Stage up-axis: " << UsdGeomGetStageUpAxis(stage) << std::endl;

    // Print the stage's linear units, or "meters per unit"
    std::cout << "Meters per unit: " << std::setprecision(5) << UsdGeomGetStageMetersPerUnit(stage) << std::endl;

    // Traverse the stage and return the first UsdGeomMesh we find
    auto range = stage->Traverse();
    for (const auto& node : range)
    {
        std::cout << node.GetPath() << std::endl;
    }

    // The stage is a sophisticated object that needs to be destroyed properly.
    // Since stage is a smart pointer we can just reset it
    stage.Reset();

    omniClientShutdown();
}

Release Notes

102.1 Point Release

  • Samples

    • OM-31648: Add a windows build tool configuration utility if the user wants to use an installed MSVC and the Windows SDK

    • Add a dome light with texture to the stage

    • OM-35991: Modify the MDL names and paths to reduce some code redundancy based on a forum post

    • Add Nucleus checkpoints to the Python sample

    • Avoid writing Nucleus checkpoints when live mode is enabled, this isn’t supported properly

    • OM-37005: Fix a bug in the Python sample batch file if the sample was installed in a path with spaces

    • Make the /Root prim the defaultPrim

    • Update Omniverse Client Library to 1.13.19

  • Omniverse Client Library

    • 1.13.19
      • OM-36925: Fix omniClientMakeRelative(“omni://host/path/”, “omni://host/path/”);

    • 1.13.18
      • OM-25931: Fixed some issues around changing and calling the log callback to reduce hangs.

      • OM-36755: Fixed possible use-after-delete issue with set_log_callback (Python).

    • 1.13.17
      • OM-34879: Hard-code “mdl” as “not a layer” to work around a problem that happens if the “usdMdl” plugin is loaded

    • 1.13.16
      • OM-36756: Fix crash that could happen if two threads read a layer at the exact same time.

    • 1.13.15
      • OM-35235: Fix various hangs by changing all bindings to release the GIL except in very specific cases.

    • 1.13.14
      • OM-34879: Fix hang in some circumstances by delaying USD plugin registration until later

      • OM-33732: Remove USD diagnostic delegate

    • 1.13.13
      • OM-36256: Fixed S3 provider from generating a bad AWS signature when Omni Cache is enabled

    • 1.13.12
      • OM-20572: Fixed setAcls

    • 1.13.11
      • OM-35397: Fixed a bug that caused Linux’s File Watcher Thread to peg the CPU in some cases.

    • 1.13.10
      • OM-32244: Fixed a very rare crash that could occur when reading a local file that another process has locked

    • 1.13.9
      • OM-35050: Fixed problem reloading a non-live layer after it’s been modified.

    • 1.13.8
      • OM-34739: Fix regression loading MDLs introduced in * 1.13.3

      • OM-33949: makeRelativeUrl prepends “./” to relative paths

      • OM-34752: Make sure local paths are always using “” inside USD on Windows

    • 1.13.7
      • OM-34696: Fixed bug when S3 + cloudfront + omni cache are all used

    • 1.13.6
      • OM-33914: Fixed crash when accessing http provider from mulitple threads simultaneously

    • 1.13.5
      • OM-26039: Fixed “Restoring checkpoint while USD stage is opened live wipes the content”

      • OM-33753: Fixed “running massive amounts of live edits together causes massive amounts of checkpoints”

      • OM-34432: Fixed “[Create] It will lose all data or hang Create in live session”
        • These were all the same underlying issue: When a layer is overwritten in live mode it was cleared and set as ‘dirty’ which would cause the next “Save()” (which happens every frame in live mode) to save the cleared layer back to the Omniverse server.

    • 1.13.4
      • OM-31830: omniClientCopy() with HTTP/S3 provider as source

      • OM-33321: Use Omni Cache 2.4.1+ new reverse proxy feature for HTTPS caching

    • 1.13.3
      • OM-33483: Don’t crash when trying to save a layer that came from a mount

      • OM-27233: Support loading non-USD files (abc, drc, etc)

      • OM-4613 & OM-34150: Support saving usda files as ascii
        • Note this change means live updates no longer work with usda files (though they technically never did – it would silently convert them to usdc files).

101.1 Point Release

  • Add Linux package for the Omniverse Launcher

  • Add a Python 3 Hello World sample

  • Update the Omniverse Client Library to 1.13

  • Update to Python 3.7

  • Add a Nucleus Checkpoint example

  • Add the ability to create/access a USD stage on local disk in the Hello World sample

100.2 Update

  • Update the Omniverse Client Library fix an issue with overlapping file writes

100.1 Point Release

  • First release

  • HelloWorld sample that demonstrates how to:

    • connect to an Omniverse server

    • create a USD stage

    • create a polygonal box and add it to the stage

    • upload an MDL material and its textures to an Omniverse server

    • bind an MDL and USD Preview Surface material to the box

    • add a light to the stage

    • move and rotate the box with live updates

    • print verbose Omniverse logs

    • open an existing stage and find a mesh to do live edits

  • OmniCLI sample that exercises most of the Omniverse Client Library API