Hello World: Populate ovstage and Step#
This tutorial shows the smallest end-to-end ovphysx workflow: create an instance, populate an ovstage Stage from USD, attach it, step simulation, and clean up resources. You can use this flow as the starting point for larger integrations.
Prerequisites#
Prepare a readable USD file for ovstage population.
Code Language#
Python#
Install the package first:
pip install ovphysx
import ovphysx
from ovphysx import PhysX
from pathlib import Path
print("Using ovphysx version: ", ovphysx.__version__)
def attach_scene(physx, usd_path):
import ovstage
if not ovstage.population.available():
raise RuntimeError("ovstage population bridge is unavailable")
stage = ovstage.Stage("ovphysx-hello-world")
ordinal = 1
try:
ovstage.population.open_usd(stage, str(usd_path), ordinal=ordinal, domains=ovstage.PopulationDomain.PHYSICS)
physx.attach_ovstage(stage, read_ordinal=ordinal)
print("Loaded scene through ovstage")
return stage
except Exception:
stage.destroy()
raise
script_dir = Path(__file__).resolve().parent
usd_path = script_dir / ".." / "data" / "links_chain_sample.usda"
# Initialize PhysX
physx = PhysX()
stage = attach_scene(physx, usd_path)
try:
# Run a simulation step
dt = 1.0 / 60.0
physx.step(dt)
print("Simulation step completed successfully")
finally:
if stage is not None:
physx.detach_ovstage()
stage.destroy()
physx.release()
print("Cleanup complete")
C#
Download the SDK from the GitHub Releases page and extract it.
CMakeLists.txt
Every C sample uses find_package(ovphysx) and links against ovphysx::ovphysx. Here is the CMakeLists.txt for hello_world_c:
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()
Build by pointing CMAKE_PREFIX_PATH at the installed SDK (refer to SDK Quickstart for details).
Source
#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;
}
Result#
After this tutorial, you can step the simulation from both Python and C and release all resources cleanly.