Skip to main content
`Ctrl`+`K`

# Quickstart

ovphysx is an SDK for ovstage/USD-based physics simulation, available as a Python wheel and a C/C++ package. This guide shows how to get started with both. You learn the required SDK layout, CMake configuration, runtime setup, and where to go next.

## Prerequisites

For both Python and C:

- Prepare a simple USD file such as `scene.usda` for ovstage population.

- x86_64 only: a CPU with AVX (Advanced Vector Extensions). Pre-built ovphysx x86_64 binaries require AVX; `ovphysx_initialize()` fails fast when AVX is unavailable. On Linux x86_64, check with `grep -qw avx /proc/cpuinfo`. Linux aarch64 wheels are unaffected.

- Install CUDA Toolkit and a compatible NVIDIA driver (recommended, but can be skipped if only CPU simulation is used).

## Quick Start by Language

### Python

Install the wheel:

    pip install ovphysx

    import ovstage
    import ovphysx
    from ovphysx import PhysX

    stage = ovstage.Stage("scene")
    ovstage.population.open_usd(
        stage, "scene.usda", ordinal=1, domains=ovstage.PopulationDomain.PHYSICS
    )

    physx = PhysX()
    physx.attach_ovstage(stage, read_ordinal=1)
    physx.step(1.0 / 60.0)
    physx.detach_ovstage()
    physx.release()
    stage.destroy()

`domains` is an OR-combinable bitmask whose ovstage default (`RENDERING`) omits physics. For arbitrary USD prefer `ALL` (equivalently `PHYSICS | RENDERING`); `PHYSICS` alone is only safe when the content is known not to put physics under native scene-graph instances — refer to Population domains.

### C/C++

Download the ovphysx SDK package from the GitHub Releases page and extract it to a local path. You also need CMake 3.16 or newer and a C or C++ compiler.

Repository source builds fetch OVStage automatically from public PyPI. The manual download below is only for users of the prebuilt OVPhysX SDK.

ovstage is not part of the SDK. ovphysx binds to the application-supplied ovstage, so the package ships no ovstage headers, library, or runtime. Download the matching native archive for your platform from the OVStage GitHub Releases page and extract it to a separate directory beside ovphysx. This release uses OVStage `0.1.0.346039`, published under the `v0.1.0` release. Do not overlay the two package trees.

`find_package(ovphysx)` pulls it in via `find_dependency(ovstage)`, so just add both roots to `CMAKE_PREFIX_PATH`. This is required even if you never call ovstage because the public ovphysx headers `#include <ovstage/...>`.

SDK Directory Layout

    ovphysx/
    ├── SKILLS.md             # Skills index
    ├── skills/               # Agent skills runbooks
    ├── include/ovphysx/     # Public headers (ovphysx.h, ovphysx_types.h, and related headers)
    ├── lib/                 # Shared libraries and CMake package config
    │   └── cmake/ovphysx/   # find_package(ovphysx) support
    ├── plugins/             # Carbonite, PhysX, and USD runtime plugins
    │   └── gpu/             # GPU-only plugins (loaded only when GPU is enabled)
    ├── samples/             # CI-tested C sample source + USD data
    ├── docs/                # Documentation (HTML + Markdown)
    ├── LICENSE.txt
    └── ovstage-THIRD-PARTY-NOTICES.txt

Build Your First App

CMakeLists.txt

The SDK ships a complete, CI-tested sample. Its CMake project links both the ovphysx and ovstage companion targets:

    cmake_minimum_required(VERSION 3.16)
    project(HelloWorldC C)

    set(CMAKE_C_STANDARD 11)
    set(CMAKE_C_STANDARD_REQUIRED ON)

    find_package(ovphysx REQUIRED)

    add_executable(hello_world_c main.c)

    # Explicitly set the language to C (not C++)
    set_source_files_properties(main.c PROPERTIES LANGUAGE C)
    set_target_properties(hello_world_c PROPERTIES
        C_STANDARD 11
        C_STANDARD_REQUIRED ON
    )

    # Add compiler-specific flags to enforce strict C compilation
    if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
        # GCC/Clang: Add -Werror=implicit-function-declaration to catch C++ leakage
        target_compile_options(hello_world_c PRIVATE
            -Werror=implicit-function-declaration
            -pedantic
        )
    endif()

    if(MSVC)
        # MSVC: Compile as C code explicitly
        target_compile_options(hello_world_c PRIVATE /TC)
    endif()

    target_link_libraries(hello_world_c PRIVATE ovphysx::ovphysx ovphysx::ovstage)
    target_include_directories(hello_world_c PRIVATE "${CMAKE_CURRENT_LIST_DIR}/../common")
    get_filename_component(OVPHYSX_TEST_DATA_DIR "${CMAKE_CURRENT_LIST_DIR}/../../data" ABSOLUTE)
    target_compile_definitions(hello_world_c PRIVATE
        OVPHYSX_TEST_DATA="${OVPHYSX_TEST_DATA_DIR}"
    )
    if(WIN32)
        ovphysx_copy_runtime_dlls(hello_world_c)
    endif()

#### Source

The sample creates and populates an ovstage instance, attaches it with the sealed read ordinal, waits for the physics step, and cleans up in lifetime-safe order:

    #include "ovphysx/ovphysx.h"
    #include "ovstage_sample.h"
    #include <stdio.h>

    static int run(void)
    {
      // Create PhysX instance with default args
      ovphysx_create_args create_args = OVPHYSX_CREATE_ARGS_DEFAULT;
      ovphysx_handle_t handle = 0;

      ovphysx_result_t result = ovphysx_create_instance(&create_args, &handle);
      if (result.status != OVPHYSX_API_SUCCESS) {
        fprintf(stderr, "Failed to create PhysX instance\n");
      ovphysx_shutdown();
        return 1;
      }

      // Populate ovstage from USD and attach it to ovphysx
      ovphysx_sample_stage_attachment_t stage_attachment = {0};
      if (!ovphysx_sample_attach_usd_with_ovstage(
              handle, OVPHYSX_TEST_DATA "/simple_physics_scene.usda", &stage_attachment)) {
        fprintf(stderr, "Failed to attach ovstage scene\n");
        ovphysx_destroy_instance(handle);
      ovphysx_shutdown();
        return 1;
      }

      // Step the simulation
      ovphysx_enqueue_result_t step_result = ovphysx_step(handle, 0.016f);
      if (step_result.status != OVPHYSX_API_SUCCESS) {
        fprintf(stderr, "Failed to step simulation\n");
        ovphysx_sample_destroy_stage(handle, &stage_attachment);
        ovphysx_destroy_instance(handle);
      ovphysx_shutdown();
        return 1;
      }

      // Wait for step to complete
      ovphysx_op_wait_result_t step_wait_result = {0};
      ovphysx_result_t step_wait_status = ovphysx_wait_op(handle, step_result.op_index, UINT64_MAX, &step_wait_result);
      int step_ok = (step_wait_status.status == OVPHYSX_API_SUCCESS && step_wait_result.num_errors == 0);
      ovphysx_destroy_wait_result(&step_wait_result);
      if (!step_ok) {
        fprintf(stderr, "Simulation step failed\n");
        ovphysx_sample_destroy_stage(handle, &stage_attachment);
        ovphysx_destroy_instance(handle);
      ovphysx_shutdown();
        return 1;
      }

      printf("Simulation step completed successfully\n");

      ovphysx_sample_destroy_stage(handle, &stage_attachment);
      ovphysx_destroy_instance(handle);
      ovphysx_shutdown();
      printf("Cleanup complete\n");

      return 0;
    }

    int main(void) {
        ovphysx_result_t init_r = ovphysx_initialize();
        if (init_r.status != OVPHYSX_API_SUCCESS) {
            fprintf(stderr, "ovphysx_initialize() failed\n");
            return 1;
        }
      int rc = run();
      return rc;
    }

Configure and Build

Point `CMAKE_PREFIX_PATH` at the SDK root (the directory containing `include/`, `lib/`, and `plugins/`) and build the bundled sample:

    cmake -B build -S /path/to/ovphysx/samples/c_samples/hello_world_c \
      -DCMAKE_PREFIX_PATH="/path/to/ovphysx;/path/to/ovstage"
    cmake --build build

## Runtime Libraries (C/C++)

### Linux

The CMake config bakes RPATH into your executable automatically. No `LD_LIBRARY_PATH` manipulation is needed. Run the binary directly.

### Windows

Use the `ovphysx_copy_runtime_dlls(<target>)` helper provided by the CMake package (already shown in the `CMakeLists.txt` example). This copies the OVPhysX DLLs and plugins next to your executable. Keep the separate OVStage package intact and add its `bin`, `bin/plugins`, `bin/plugins/omni.client.lib`, and `bin/plugins/omni.usd_resolver` directories to the process `PATH` before launch.

    $env:OVSTAGE_ROOT = "C:\path\to\extracted\ovstage"
    $env:PATH = "$env:OVSTAGE_ROOT\bin;$env:OVSTAGE_ROOT\bin\plugins;$env:OVSTAGE_ROOT\bin\plugins\omni.client.lib;$env:OVSTAGE_ROOT\bin\plugins\omni.usd_resolver;$env:PATH"

## Result

You now have a minimal C or C++ application that links against `ovphysx::ovphysx`, consumes an application-owned ovstage, and runs a simulation step.

## Next Steps

- Full C API reference: refer to the C API Reference

- More tutorials: Hello World, Tensor Bindings, Contact Binding