Getting Started#
Try the Samples#
The best way to get started with the OpenUSD Exchange SDK is to try out the OpenUSD Exchange Samples. These are simple applications that showcase many features and key concepts of the SDK.
You can execute the samples to try them out, learn from their source code, and modify them to experiment with OpenUSD and the OpenUSD Exchange SDK for yourself.
Get the Samples#
The OpenUSD Exchange Samples are available on GitHub. You can clone the repository or download the source as a zip file.
Build#
To try the samples you will need to build them from source. The included build scripts make it easy.
This project requires “make” and “g++”.
Open a terminal.
To obtain “make” type
sudo apt install make
(Ubuntu/Debian), oryum install make
(CentOS/RHEL).For “g++” type
sudo apt install g++
(Ubuntu/Debian), oryum install gcc-c++
(CentOS/RHEL).Use the provided build script to download all other dependencies (e.g OpenUSD), create the Makefiles, and compile the code:
./repo.sh build
This project requires Microsoft Visual Studio 2019 or newer.
Download & install Visual Studio with C++.
Use the provided build script to download all dependencies (e.g OpenUSD), create the projects, and compile the code:
.\repo.bat build
Run#
Once you have built the samples, you can run their executables to try them. All of the compiled samples are executed with a run
script with the
program name as the first argument. There are many samples under the source
folder, like createStage
, createLights
, createTransforms
, etc.
Use the run.sh
script (e.g. ./run.sh createStage
) to execute each program with a pre-configured environment.
For command line argument help, use --help
./run.sh createStage --help
Use the python.sh
script (e.g. ./python.sh source/createStage/createStage.py
) to execute each program with a pre-configured environment.
For command line argument help, use --help
./python.sh source/createStage/createStage.py --help
Use the --help
flag for each of the sample executables to learn more about the optional arguments that they accept. (e.g. ./run.sh createStage --help
)
Use the run.bat
script (e.g. .\run.bat createStage
) to execute each program with a pre-configured environment.
For command line argument help, use --help
.\run.bat createStage --help
Use the python.bat
script (e.g. .\python.bat source\createStage\createStage.py
) to execute each program with a pre-configured environment.
For command line argument help, use --help
.\python.bat source\createStage\createStage.py --help
Use the --help
flag for each of the sample executables to learn more about the optional arguments that they accept. (e.g. .\run.bat createStage --help
)
See also the OpenUSD Exchange Samples README for more detailed descriptions and documentation about the individual samples.
Experiment#
Once you have oriented yourself with the samples that interest you, try modifying the source code in the source/
directory of the repository to experiment with the SDK. Once you’ve made your change, just repeat the Build and Run steps in this guide and test out your change.
Proceed to the next section to learn how to start building your own application to convert data to OpenUSD.
Integrate into an Application#
The next step to familiarize yourself with the OpenUSD Exchange SDK is to create a simple standalone application.
This section will teach you how to create an application that opens a UsdStage
, reports basic stage configuration details, and lists all of the UsdPrim
paths.
This walkthrough will use these tokens:
$project_root
- the base directory where the project application is locatedTo keep things clean, it is recommended that this is completely separate from either the OpenUSD Exchange SDK or Exchange Samples repo folders
$config
- the build configuration (debug
orrelease
)$platform
- the platform (linux-x86_64
orwindows-x86_64
)
Install the SDK#
Assembling the minimal requirements for the OpenUSD Exchange SDK can be complicated, so there is an install_usdex script that developers run to gather everything into one _install
folder. This folder can then be copied into the project structure of the developer’s application.
Running these commands from the Sample’s root folder will generate the _install
folder for both debug and release configurations and deep copy them to wherever the sample project is located. Note that if running the install script from the Exchange Samples, it is necessary to build them first:
./repo.sh build ./repo.sh install_usdex --config release --install-python-libs ./repo.sh install_usdex --config debug --install-python-libs cp -Lr _install $project_root/usdex
repo.bat build repo.bat install_usdex --config release --install-python-libs repo.bat install_usdex --config debug --install-python-libs robocopy /s _install $project_root\usdex > NUL
This tree describes the proposed file layout for the project:
$project_root
│ Makefile or UsdTraverse.sln|vsproj
│ UsdTraverse.cpp
│ ...
└───usdex
├───target-deps <----- build dependencies
│ ├───omni_transcoding
│ ├───python
│ ├───usd
│ └───usd-exchange
└───$platform/$config <----- runtime dependencies
├───lib
└───python
├───pxr
└───usdex
Note
The install_usdex
script may be run from either the Exchange Samples or the Exchange SDK root directory, it is provided with both repositories. If repo.bat|sh install_usdex
is run from within the usd-exchange repository root, there is no need to run repo.bat|sh build
first. The version of OpenUSD Exchange that is downloaded will match the top line of the USD Exchange repository’s [CHANGELOG.md](../CHANGELOG.md) if no --version
argument is provided.
This _install
folder will be copied into $project_root/usdex
for this walkthrough. Note that the target-deps
folder contains soft links on Linux and junctions on Windows, so any time it is copied, it requires deep copy commands or options.
For more details on choosing build flavors & features, or different versions of the SDK, see the install_usdex documentation.
Runtime Dependencies#
The install_usdex
tool will assemble the exact runtime requirements based on the build flavor you have selected, so the easiest approach is to copy the file tree that it generated.
There is some flexibility however. For more thorough details about how to deploy the runtime dependencies for an application or plugin using the OpenUSD Exchange SDK, see the detailed runtime requirements.
Sample Program#
The application performs a few simple things with OpenUSD and the OpenUSD Exchange SDK:
Expects one argument, the path to a USD stage
Acceptable forms:
C:/USD/helloworld.usd
or/tmp/USD/helloworld.usd
- an absolute pathA relative path based on the CWD of the program (
sample.usda
)
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
If the prim is
xformable
then print its position
It is included here to copy into a UsdTraverse.cpp
file within $project_root
// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: MIT
//
#include <usdex/core/XformAlgo.h>
#include <pxr/usd/usd/primRange.h>
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/usdGeom/metrics.h>
#include <pxr/usd/usdGeom/xformable.h>
#include <iostream>
// The program expects one argument, a path to a USD file
int main(int argc, char* argv[])
{
if (argc != 2)
{
std::cout << "Please provide a local file path to a USD stage to read." << std::endl;
return -1;
}
std::cout << "OpenUSD Stage Traversal: " << argv[1] << std::endl;
pxr::UsdStageRefPtr stage = pxr::UsdStage::Open(argv[1]);
if (!stage)
{
std::cout << "Failure to open stage. Exiting." << std::endl;
return -2;
}
// Print the stage metadata metrics
std::cout << "Stage up-axis: " << pxr::UsdGeomGetStageUpAxis(stage) << std::endl;
std::cout << "Meters per unit: " << pxr::UsdGeomGetStageMetersPerUnit(stage) << std::endl;
// Traverse the stage, print all prim names, print transformable prim positions
pxr::UsdPrimRange range = stage->Traverse();
for (const auto& prim : range)
{
std::cout << prim.GetPath();
if (pxr::UsdGeomXformable(prim))
{
pxr::GfTransform xform = usdex::core::getLocalTransform(prim);
std::cout << ":" << xform.GetTranslation();
}
std::cout << std::endl;
}
}
Build Configuration#
Linux#
For Linux, all of the build configuration settings are described in the Makefile included here:
# SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: MIT
# This makefile is a simple example for an application, or converter for including, linking, and executing with
# OpenUSD and the OpenUSD Exchange SDK
#
# By default it will build against the release version of OpenUSD, to build against the debug version run `make CONFIG=debug`.
# The expectation is that OpenUSD, the OpenUSD Exchange SDK, and other dependencies are present in the `$project_root/usdex/target-deps` directory
BOOSTVER = boost-1_78
DEPSDIR = $(CURDIR)/usdex/target-deps
PYTHONVER = python3.10
PROGRAMNAME = UsdTraverse
ifndef CONFIG
CONFIG=release
endif
ifndef TARGETDIR
TARGETDIR = $(CURDIR)/$(CONFIG)
endif
# Debug vs. Release differences
ifeq ($(CONFIG),debug)
CONFIG_DEFINES += -g -DDEBUG -O0 -DTBB_USE_DEBUG=1
else ifeq ($(CONFIG),release)
CONFIG_DEFINES += -DNDEBUG -O2
endif
# ABI Settings
ifndef ABI_DEFINES
ABI_DEFINES = -D_GLIBCXX_USE_CXX11_ABI=1 -std=c++17
endif
# Ignored Warnings
ifndef IGNORED_WARNINGS
IGNORED_WARNINGS = -Wno-deprecated -DTBB_SUPPRESS_DEPRECATED_MESSAGES
endif
# Include search directories
USDEX_INCLUDE_DIRS = \
-isystem $(DEPSDIR)/usd-exchange/$(CONFIG)/include \
-isystem $(DEPSDIR)/usd/$(CONFIG)/include \
-isystem $(DEPSDIR)/usd/$(CONFIG)/include/$(BOOSTVER)
# USD libs (most of these not required, but this is a proper set for a fully featured converter)
USD_LIBS = \
-lboost_python310 \
-lusd_ar \
-lusd_arch \
-lusd_gf \
-lusd_js \
-lusd_kind \
-lusd_pcp \
-lusd_plug \
-lusd_sdf \
-lusd_tf \
-lusd_trace \
-lusd_usd \
-lusd_usdGeom \
-lusd_usdLux \
-lusd_usdShade \
-lusd_usdUtils \
-lusd_vt \
-lusd_work
USDEX_LIBS = \
-lusdex_core \
-lomni_transcoding
# Library dependency directories
USDEX_LIB_DIRS = \
-L$(DEPSDIR)/usd-exchange/$(CONFIG)/lib \
-L$(DEPSDIR)/omni_transcoding/$(CONFIG)/lib \
-L$(DEPSDIR)/usd/$(CONFIG)/lib
# Python specifics
ifndef PYTHON_INCLUDE_DIR
PYTHON_INCLUDE_DIR = -isystem $(DEPSDIR)/python/include/$(PYTHONVER)
endif
ifndef PYTHON_LIB
PYTHON_LIB = -l$(PYTHONVER)
endif
ifndef PYTHON_LIB_DIR
PYTHON_LIB_DIR = -L$(DEPSDIR)/python/lib
endif
# Common flags
CXXFLAGS += $(CONFIG_DEFINES) $(ABI_DEFINES) $(IGNORED_WARNINGS) -m64
INCLUDES += $(USDEX_INCLUDE_DIRS) $(PYTHON_INCLUDE_DIR)
LIBS += $(USD_LIBS) $(USDEX_LIBS) $(PYTHON_LIB)
LDFLAGS += $(USDEX_LIB_DIRS) $(PYTHON_LIB_DIR)
OBJS = $(TARGETDIR)/$(PROGRAMNAME).o
# Build Targets
all: $(TARGETDIR)/$(PROGRAMNAME)
# $@ matches the target; $< matches the first dependent
$(TARGETDIR)/$(PROGRAMNAME): $(OBJS)
echo Linking $(PROGRAMNAME)
g++ -o $@ $< $(LDFLAGS) $(LIBS)
$(OBJS): $(PROGRAMNAME).cpp | $(TARGETDIR)
g++ $(INCLUDES) $(CXXFLAGS) -c $< -o $@
$(TARGETDIR):
@echo Creating $(TARGETDIR)
@mkdir -p $(TARGETDIR)
clean:
rm -rf $(TARGETDIR)
Windows#
Create a new Visual Studio 2019 or 2022 project based on the C++ Console App
, Empty Project
template and call it UsdTraverse
. Make sure that the solution and project files live in $project_root
. Add the CPP source that traverses the USD file to the project. All of the settings specified in this section are found by right clicking on the created project and selecting Properties
from within Visual Studio.
Note
The OpenUSD Exchange Samples include Visual Studio solution and project files with all of the below build configuration settings setup. Because Visual Studio solutions aren’t as portable as Makefiles, your mileage may vary with them and you may need to start from scratch with a new solution.
Header Include Paths#
VC++ Directories > External Include Directories
usdex/target-deps/usd-exchange/$(CONFIGURATION)/include
usdex/target-deps/python/include
usdex/target-deps/usd/$(CONFIGURATION)/include
usdex/target-deps/usd/$(CONFIGURATION)/include/boost-1_78
Library Include Paths#
VC++ Directories > Library Directories
usdex/target-deps/usd-exchange/$(CONFIGURATION)/lib
usdex/target-deps/python/libs
usdex/target-deps/usd/$(CONFIGURATION)/lib
Compiler Flags from Settings#
Windows requires the
/std:c++17
flag, this can be enabled by setting theC/C++ > Language > C++ Language Standard
toISO C++17 Standard
.The OpenUSD C++ headers generate many compiler warnings, the
/external:W0
flag will quiet them. SetC/C++ > External Includes > External Header Warning Level
toTurn Off All Warnings
(if the include folders were put into theExternal Include Directories
list).
Preprocessor Definitions#
C/C++ > Preprocessor > Preprocessor Definitions
(all configurations)
BOOST_LIB_TOOLSET="vc142"
NOMINMAX
TBB_SUPPRESS_DEPRECATED_MESSAGES
Note: the debug configuration will need to specify to use debug TBB
TBB_USE_DEBUG=1
Libraries#
Linker > Input > Additional Dependencies
(All configurations)
usdex_core.lib
usd_arch.lib
usd_gf.lib
usd_kind.lib
usd_pcp.lib
usd_plug.lib
usd_sdf.lib
usd_tf.lib
usd_usd.lib
usd_usdGeom.lib
usd_usdLux.lib
usd_usdUtils.lib
usd_vt.lib
usd_ar.lib
For the release configuration
boost_python310-vc142-mt-x64-1_78.lib
For the debug configuration
boost_python310-vc142-mt-gd-x64-1_78.lib
Each OpenUSD module must be linked by the application separately. The list above is a subset of all of them, but actually more than what the example requires. For instance, usd_usdLux.lib
includes the UsdLux : USD Lighting Schema, but the example doesn’t actually use any of the UsdLux interface. The developer can trim this library list according to the needs of their application.
Debugger Environment#
If you want to launch or debug the sample from within Visual Studio, the PATH
environment variable must be set in the settings:
Configuration Properties > Debugging
(All configurations)
PATH=usdex/windows-x86_64/$(CONFIGURATION)/lib
Runtime Environment#
The application must be able to find the shared libraries located in usdex/$platform/$config/lib
. These variables should be setup from a launching script, Visual Studio debugger settings, or from within the application itself before using the OpenUSD Exchange Core module.
run_usdex_app.sh
#!/bin/bash set -e export RUNTIME_PATH=./usdex/linux-x86_64/release export LD_LIBRARY_PATH=${RUNTIME_PATH}/lib:${LD_LIBRARY_PATH} ./release/UsdTraverse "$@"
run_usdex_app.bat
@echo off setlocal set RUNTIME_PATH=usdex/windows-x86_64/release set PATH=%RUNTIME_PATH%/lib;%PATH% x64\release\UsdTraverse.exe %*
Warning
If OpenUSD is installed on your system and its paths are in your PATH
environment variable, the samples may not run correctly.
Testing the Results#
It is a good idea to author test data in your source format which you can use during development and for regression testing.
Once your data is converted to USD, it is recommended to test it for correctness & compliance with OpenUSD, using a tool like the Omniverse Asset Validator. It is a Python module & CLI which you can use to run a suite of validation rules that check for common USD authoring mistakes.
Note
While the Asset Validator was developed as a part of Omniverse, Kit is not required to use it. You can see example uses in the OpenUSD Exchange Samples.
If you are using Python’s unittest framework for your regression testing, consider trying the usdex.test
python module in your test suite. It includes a few unittest.TestCase
derived classes to simplify some common OpenUSD testing scenarios, including the Asset Validator mentioned above (e.g self.assertIsValidUsd()
), as well as context managers for asserting OpenUSD and OpenUSD Exchange Diagnostic logs.
If you require C++ testing, consider using doctest and the usdex/test
headers, which provide similar diagnostic log assertions for the doctest framework.
Debugging#
Diagnostic Logs#
OpenUSD provides diagnostics facilities to issue coding errors, runtime errors, warnings and status messages. The OpenUSD Exchange SDK also uses these TfDiagnostic
messages to relay detailed status, warning, and error conditions the user.
There are functions to activate and configure a specialized “diagnostics delegate” within the SDK detailed in the Diagnostic Messages group.
Users may immediately notice that the OpenUSD Exchange SDK function, usdex::core::createStage()
emits a Status message to stdout
like:
Status: in saveStage at line 254 of ...\source\core\library\StageAlgo.cpp -- Saving "stage with rootLayer @.../AppData/Local/Temp/usdex/sample.usdc@, sessionLayer @anon:000001927295CA60:sample-session.usda@"
One way to filter out these messages is to activate the SDK’s diagnostic delegate using usdex::core::activateDiagnosticsDelegate()
. Once this diagnostics delegate is engaged, the default diagnostics level emitted is “warning”, so the “status” messages will be hidden.
TF_DEBUG Logs#
OpenUSD ships with a debug logging feature that prints to stdout
. You can configure OpenUSD logging using the TF_DEBUG
environment variable or the TfDebug
interface. All of the debug message types are available using the TfDebug::GetDebugSymbolDescriptions()
method.
Here are some useful examples that are present in recent USD releases:
AR_RESOLVER_INIT : Print debug output during asset resolver initialization
PLUG_LOAD : Plugin loading
PLUG_REGISTRATION : Plugin registration
USD_CHANGES : USD change processing
USD_STAGE_LIFETIMES : USD stage ctor/dtor messages
Additionally, OpenUSD Exchange SDK adds its own TF_DEBUG settings:
USDEX_TRANSCODING_ERROR : Indicates when UsdPrim or UsdProperty name string encoding fails
The debug variables can be combined using wildcards to enable multiple symbol messages:
TF_DEBUG=* : Enable all debug symbols
TF_DEBUG='PLUG_* AR_*' : Enable debug symbols for all ``PLUG_*`` and ``AR_*`` messages
TF_DEBUG=USDEX_* : Enable only the debug symbols for OpenUSD Exchange SDK messages
Attaching a Debugger#
TF_DEBUG
can be set to cause a debug break in a debugger when a warning, error, or fatal diagnostic message is emitted.
TF_ATTACH_DEBUGGER_ON_ERROR : attach/stop in a debugger for all errors
TF_ATTACH_DEBUGGER_ON_FATAL_ERROR : attach/stop in a debugger for fatal errors
TF_ATTACH_DEBUGGER_ON_WARNING : attach/stop in a debugger for all warnings
To debug break in any of these while a debugger is attached to the process:
TF_DEBUG=TF_ATTACH_DEBUGGER*
ARCH_DEBUGGER_TRAP/ArchDebuggerTrap() is a direct way to break if a debugger is attached from within application code.