Plugins vs Applications

The most common kind of Omniverse Connector is a plugin or extension to an existing Digital Content Creation (DCC) Application.

This generally takes the form of a dynamic library and/or python module that is loaded into the DCC via a native plugin mechanism, or perhaps built into the DCC directly, in the case of a single 3rd Party developing both the DCC and the Connector.

However, it is also possible to develop an Omniverse Connector as its own standalone application (executable). In fact, the Omniverse Carbonite SDK used within Connect SDK was originally intended for this purpose.

By following a few Carbonite rules for application development, you can turn any executable into an Omniverse application. Connect SDK helps simplify this process.

Note

This is the same idea as kit.exe itself and we use the same underling Carb APIs to accomplish it.

When to build an app vs a library/module

The most common use for Omniverse Connector Applications is for unit testing (and integration testing) of Omniverse Connector dynamic libraries. Often, we write tests as standalone executables, and those apps must be able to bootstrap the Carbonite Framework in order to use underlying subsystems like logging.

Its also useful when writing simpler commandline applications, such as those found in the Connect Samples, or when writing standalone data converters (i.e. proprietary data in, USD out).

When integrating Omniverse into an existing DCC Application, a library/module is the recommended approach.

Initializing a Connector Plugin

When building a Connector as a plugin, there is one source code requirement from Connect SDK and one from Carbonite. We will cover these in detail below, but the minimal example is as follows:

#include <omni/connect/core/Core.h>

// Declare the Omniverse globals & default log channel
OMNI_APP_GLOBALS("example.plugin", "Native (C++) example Omniverse Connector Plugin");

bool startOmniverseConnector()
{
    // Acquire the Carbonite Framework and start the Connect SDK core module
    OMNICONNECTCORE_INIT();

    // Use initialization status to drive your logic
    if (!omni::connect::core::initialized())
    {
        return false;
    }

    // continue with your logic
}

Initializing a Connector Application

When building a Connector as an Application, there is one source code requirement from Connect SDK and one from Carbonite. This is subtly different from the plugin example above. We will cover these in detail below, but the minimal example is as follows:

#include <omni/connect/core/Core.h>

// Declare the Omniverse globals & default log channel
OMNI_APP_GLOBALS("example.app", "Native (C++) example Omniverse Connector Application");

int main(int argc, char** argv)
{
    // Acquire the Carbonite Framework and start the Connect SDK core module
    OMNICONNECTCORE_INIT();

    // Failed initialization likely indicates the application should exit
    if (!omni::connect::core::initialized())
    {
        return EXIT_FAILURE;
    }

    // continue with your app
}

Declare the Omniverse Globals

First, for either a plugin or an application, you must declare the OMNI_APP_GLOBALS as follows:

OMNI_APP_GLOBALS("example", "Native (C++) example Omniverse Connector");

This must be done statically, in the global namespace, and exactly once per library or executable. See Declaration of Globals for a detailed historical explanation.

Important

Note this is required if you wish to emit OMNI_LOG messages or use any Carbonite subsystems directly. Each module must declare the globals exactly once.

We suggest you use different names per module to avoid confusion, and ideally claim your own “namespace” so that messages emitted to users are clear. For example:

[Info] [example.app] This is a message from your Connector Application
[Info] [example.plugin] This is a message from your Connector Plugin

Initialize the Omniverse Frameworks

Next, you must initialize the Carbonite Framework. In the case of an application, this should usually be done inside main, but for a plugin it can be called from any runtime function. In either case, it is done via:

OMNICONNECTCORE_INIT();

This will configure & then start the Carbonite Framework, several required Carbonite plugins, Omniverse Client Library, and Omniverse USD Resolver, all based on the configuration files you have provided.

Warning

Some documents will refer to OMNI_CORE_INIT, which is an essential requirement for Omniverse Applications, but it explicitly should not be called for typical Omniverse Connectors that are plugins to 3rd Party applications. Connector developers should use OMNICONNECTCORE_INIT instead, unless there is an explicit need for OMNI_CORE_INIT.

To check initialization status, you can call:

omni::connect::core::initialized()

If initialization failed, you may want to return a failure status, or possibly perform some dynamic configuration and try again, such as:

auto settings = carb::getCachedInterface<carb::settings::ISettings>();
settings->setBool("/foo/bar", false);
bool status = omni::connect::core::startup();

Optionally embed Python

Whether developing a plugin or an application, you can optionally run an embedded python interpreter within your application. This bootstrapping is handled automatically during omni::connect::core::startup() (and OMNICONNECTCORE_INIT()).

See python configuration for details.