Created Modified

Technical report

USD scene preservation for Newton RTX

Software
Newton 1.7 development · OVRTX 0.5 · ovstage 0.2
Evidence
13 research runs · RTX 4090 / Windows

Abstract

Newton’s USD importer reconstructs a limited visual scene, which can discard authored appearance. Meanwhile, ovnewton imports physics from ovstage through a second implementation of many of Newton’s import rules. This report explains the two workflows and proposes separate ownership for scene preservation and physics interpretation: retain the composed scene for OVRTX, centralize physics policy in Newton, and keep ovnewton as an optional adapter. Isaac Lab asset comparisons and synthetic pose replay support the rendering approach; complete task compatibility and the shared importer remain unproven. Publication overhead is substantial for 64 moving robots.

Contents

Newton prototype branch · API and reproduction.
Implemented: external-scene rendering and CPU/CUDA pose transport. Proposed: the complete viewer upgrade, dependency changes and shared physics importer.

1. Motivation and component roles

USD (Universal Scene Description) combines referenced assets, overrides, materials, lights and physics into a composed scene. Newton converts that scene into a simulation model and portable visual shapes. Reconstructing an RTX scene from those shapes can lose material networks, subdivision settings or environment content. Issue #4051 requests visual and lighting parity with Omniverse Kit; extending Newton’s material parser addresses individual losses but also gives the physics engine more rendering semantics to maintain.

The proposal addresses two separate problems: preserve authored appearance for rendering, and eliminate duplicated physics interpretation. ovstage enables the first; adopting it does not automatically solve the second.

Component Responsibility
ovpopulation — load Population component that uses OpenUSD to load composed rendering and/or physics data into ovstage. Python entry point: ovstage.population.open_usd(...).
ovstage — share Runtime scene store for prims (scene objects), hierarchy, attributes and tensor access. Increasing publication ordinals identify updates and coordinate when consumers may read them. It is neither a physics solver nor a Newton model builder.
ovnewton — connect Imports ovstage physics into Newton and synchronizes simulation state with the stage. It currently contains its own physics interpretation; the proposal replaces that policy with a shared Newton implementation.
OVRTX / ViewerRTX — render / display OVRTX renders an attached ovstage. Newton’s ViewerRTX provides the viewer interface and displays render outputs. Neither requires ovnewton merely to render a stage.
Table 1. Component responsibilities and the proposed integration boundary.

The intended division follows OVRTX’s external-stage architecture. OpenUSD still handles USD composition through population; Newton should interpret the physics needed for simulation, while the rendering backend interprets supported visual schemas.

2. Current workflows and duplicated parsing

Ordinary Newton application: call ModelBuilder.add_usd(...), finalize the model, then run a solver and viewer. Newton’s OpenUSD importer reads physics and extracts portable visuals. The existing generated-scene ViewerRTX path builds a new render scene from those visuals.

Application using ovnewton: populate an ovstage, import it with ovnewton.add_ovstage(...), finalize a Newton model, and attach a state binding. The application runs the solver and publishes its results to the same stage that OVRTX renders. These are alternative import routes; an application need not run both physics importers.

Figure 1. Current alternative import routes. USD composition is handled by OpenUSD; Newton-specific physics interpretation exists in both importers. The duplication is maintained code, not necessarily two imports in one application.

How an application uses ovnewton today

Listing 1 · Python
builder = newton.ModelBuilder()
result = ovnewton.add_ovstage(builder, stage, ordinal=ordinal)
model = builder.finalize(
    skip_validation_joints=result.has_orphan_joints,
)
binding = ovnewton.attach_ovstage(
    stage, model=model, ordinal=ordinal,
)

# After the solver advances state for a frame:
ordinal += 1
binding.update_to_ovstage(state, ordinal=ordinal)
stage.advance_write_floor(ordinal).wait()
renderer.step(
    render_products={product}, delta_time=dt, ordinal=ordinal,
)

Current API excerpt from the inspected ovnewton example (repository access required). Assumes a populated, published stage, renderer, render product, solver state and frame duration dt. Register solver-specific attributes before import. add_ovstage currently requires an otherwise empty builder; attach_ovstage(model=...) binds an existing model, while omitting model imports and finalizes one for convenience.

“Parsing ovstage” means querying runtime attributes and interpreting their physics meaning, rather than opening USD files again in Python. The inspected implementation separates this work into three layers:

Layer What ovnewton does today
Read — _stage.py Queries prim paths and fixed-length or variable-length attribute columns at a published ordinal; fetches groups and copies values into CPU arrays. This is a source reader, not a second USD composition engine.
Interpret — _parse.py Extracts units, gravity, bodies, materials, colliders, joints and hierarchy; derives relationships and some converted values.
Build — _build.py Chooses Newton geometry, resolves mass/inertia and material defaults, creates bodies and joints, and applies initial state. These decisions overlap with Newton’s OpenUSD importer.
Table 2. How the inspected ovnewton implementation reads and interprets ovstage.

For example, both paths decide how authored mass interacts with density-derived mass and missing inertia, how units and joint angles are converted, and how colliders and joints become Newton objects. A policy change can therefore require two fixes and two sets of coverage. The duplication is physics semantics across two implementations, even if each reads its own source efficiently. Newton importer, ovnewton interpretation, model construction.

Per-frame synchronization is separate from import. ovnewton publishes body poses, velocities and supported joint state, and can read supported stage state and drive targets back into Newton. It does not rebuild the physics model each frame. The current binding uses body/joint labels as prim paths and must be recreated after incompatible topology changes. Binding contract.

3. Proposed scene and viewer ownership

Preserve the composed render scene. Newton imports physics and publishes motion through a body-to-prim mapping, which associates simulated bodies with scene objects. Keep scene ownership and live USD prims outside Model; retain portable visuals for other viewers.

A source prim path on each visual shape is useful provenance but insufficient as the scene contract: it can omit lights, environment and material-binding context. Storing live UsdPrim handles also ties their validity to the source stage’s lifetime. Simulation bodies and render prims need not correspond one-to-one, especially after body collapse or instancing. An application-owned stage plus explicit bindings preserves that distinction.

Figure 2. Proposed runtime ownership. Appearance stays in ovstage; Newton writes poses. ovnewton would reuse the optional pose transport.

ViewerRTX can remain independent of ovnewton. Put shared pose transport in Newton’s optional ovstage integration; ovnewton delegates pose writes to it. OVRTX renders; ViewerRTX presents the result.

Viewer mode Scene ownership
Existing USD / Isaac Lab scene Application owns stage, renderer and publication; ViewerRTX borrows them.
Procedural Newton example Viewer creates its stage, geometry, camera and lights; uses the same transport and render path.
Table 3. Scene ownership in the two ViewerRTX modes.

The prototype implements borrowed-scene rendering and explicit CPU/CUDA pose bindings. Its ordinary physics import can still use Newton’s existing OpenUSD importer while population loads the render scene. This proves the rendering boundary, not unified import or a single startup traversal.

4. Shared physics import and future usage

One physics interpretation, two source readers. Newton owns units, mass/inertia, collision geometry and joint construction. The OpenUSD reader and ovnewton’s ovstage reader supply source facts to that implementation. Moving ovnewton’s parser into Newton while retaining the old parser would preserve the duplication.

Figure 3. Proposed import ownership. Two source readers supply facts to one Newton implementation of physics interpretation. This shared importer is not implemented by the rendering prototype.

The reader contract must carry values, units, hierarchy, stable source identities and whether a value was authored, inherited/defaulted or blocked. A resolved number alone can lose information needed to choose a Newton default. Readers also need a common representation of instances and their transforms. ovstage does not need to acquire Newton-specific model-building policy.

Application Proposed user-facing workflow
USD file → Newton Keep builder.add_usd(...) as the convenience entry point. It delegates physics construction to the shared importer; portable viewers remain available. An RTX application additionally preserves the source scene.
Existing ovstage → Newton Keep the ovnewton.add_ovstage(...) / finalize / attach lifecycle above. Internally, the adapter reads ovstage facts and calls the same Newton importer instead of its own physics policy.
Procedural Newton model → RTX ViewerRTX creates an ovstage and uses shared pose transport. No ovnewton import is needed.
Table 4. Proposed workflows preserve application entry points while sharing physics policy.

Dependency direction: ovnewton depends on Newton; Newton’s optional RTX integration depends on ovstage/OVRTX. Newton does not depend on ovnewton. ovnewton retains its useful state/control synchronization and convenience API, delegating common pose writes to Newton’s transport. Sharing pose transport alone does not unify the physics importers.

Mapping contract: keep a binding object beside the model with prim paths, stable body identities and rest transforms. Resolve final body indices after construction, and remap bindings when models are cloned, bodies are collapsed or arrays are reordered. The prototype requires final indices explicitly; automatic remapping is proposed work. The application owns stage lifetime and publication.

Order / owner Deliverable Done when
1 · Newton Complete the viewer upgrade in §5; keep the existing USD importer during transition. Both viewer modes pass headless/window, camera, overlay, deformation and cleanup checks on the qualified runtime pair.
2 · Newton + ovnewton Define source facts and remappable bindings; extract one physics importer in Newton and replace both existing policy paths with calls to it. ovnewton reuses pose transport. The two readers produce equivalent models for mass/density/inertia, units, joints and defaults; mapping tests cover cloning, collapse and reordering.
3 · ovstage + ovnewton Close value-provenance and instanced-collider gaps; align supported Newton and ovstage versions. ANYmal, Franka and Cartpole import correctly with one jointly tested dependency set.
Table 5. Implementation order, repository ownership and acceptance criteria.

Steps 2–3 proceed together. Inspected ovnewton pins Newton >=1.5,<1.6 and ovstage 0.2.0.378985; it cannot simply be added to Newton 1.7 development. That alignment is separate from the viewer-only runtime pair below. These are findings at the linked source revision, not claims about every later release.

5. OVRTX upgrade in Newton

Migrate the viewer before unifying the importers. Newton’s rtx extra allows ovrtx>=0.3; its generated-scene path still calls deprecated renderer scene APIs. A version bump alone leaves that migration unfinished. Current code, OVRTX architecture.

Change in Newton Concrete replacement
Qualify the runtime pair Start with tested ovrtx==0.5.0.377615 + ovstage==0.2.0.377349 in optional newton[rtx]; replace the open-ended renderer requirement. Core stays independent.
Separate scene creation from display Remove ViewerRTX’s ViewerUSD inheritance. Compose an owned-scene builder or borrowed scene with one render-product consumer. Existing USD generation can bootstrap owned scenes once.
Move scene operations to ovstage Replace renderer open_usd, bindings and attribute writes with population, cached stage queries and tensor writes. Port cameras, visibility, meshes and debug overlays too.
Adopt the 0.5 interfaces Use DLPack tensor interchange, Boolean reset flags and full RenderVar output paths; remove .tensor wrappers and raw DLTensor construction.
Table 6. Required changes for the OVRTX 0.5 migration.

Load once — current APIs

Listing 2 · Python
ovrtx.register_schema_paths()
renderer = ovrtx.Renderer(config=ovrtx.RendererConfig(sync_mode=True))
stage = ovstage.Stage("scene")

renderer.attach_ovstage(stage)
ovstage.population.open_usd(
    stage,
    scene_usd,
    ordinal=1,
    domains=ovstage.PopulationDomain.ALL,
)
stage.advance_write_floor(1).wait()

Publish, then render — prototype API

Listing 3 · Python
binding = OvstageBodyBinding(
    stage,
    model,
    ordinal=1,
    prim_paths=paths,
    body_indices=indices,
    body_local_transforms=offsets,
)
viewer = ViewerRTX(
    stage=stage,
    renderer=renderer,
    render_product=product,
)

# Finish rendering before the next write.
binding.write(state, ordinal=frame)
stage.advance_write_floor(frame).wait()
viewer.render(ordinal=frame)  # frame starts at 2

Excerpts assume an authored camera/RenderProduct and final-model mappings. Register additional physics schemas before population. See imports and cleanup and 0.5 API changes. The prototype window is a fixed-camera preview; full interaction still needs porting.

6. Visual comparison

Both sides use OVRTX 0.5 with matched camera, lighting and authored settings. These are Isaac Lab asset-derived scenes, including a generated heightfield; complete reinforcement-learning (RL) tasks and parity with Omniverse Kit rendering remain untested. Select a scene and compare the overlay.

ANYmal on an Isaac Lab heightfield

OVRTX 0.5 · 640 × 480 pixels
Reconstructed Newton visualsANYmal on an Isaac Lab heightfield: reconstructed from Newton’s portable visuals
Preserved source in ovstageANYmal on an Isaac Lab heightfield: original scene rendered through ovstage
Figure 4. ANYmal on an Isaac Lab heightfield. Subdivision and surface appearance differ after visual reconstruction. The source side uses the Newton prototype’s external-scene API.

Preserving the source addresses appearance discarded during import in #4051. Exact Kit matching still depends on backend features, exposure, color management and temporal settings.

7. Performance and qualification

Measured result Required follow-up
41–46 ms/frame for 64 moving ANYmals, before physics Profile publication before treating this as suitable for large RL workloads.
20–21 ms in global publication alone ovstage/OVRTX team: reduce commit cost and retest moving scenes.
+164–812 MiB GPU allocation for small source scenes Set workload-specific memory budgets; preserved appearance has a measurable cost.
Earlier import: 52.5 → 7.6 s without visual extraction Promising duplicate-work reduction; separate OVRTX 0.3 experiment, not a clone-pipeline comparison.
Table 7. Measured costs and their implications for workload qualification.

13 research runs · RTX 4090 / Windows · 640 × 480 · ≥30 s warmup + 60 frames. Synthetic pose replay, not solver execution; mostly one process repetition. GPU figures are allocation snapshots. Prototype: 64 robots at 41.4 ms/frame, including 22.5 ms encoding/writes/publication, without importing PXR or ovnewton in the replay’s Python process. Population still uses OpenUSD internally.

Inspect all 13 runs and measurement definitions
Scene / input / stageWorkloadPopulate (s)Frame median (ms)Frame p95 (ms)Publish median (ms)CPU (MiB)GPU (MiB)
anymal_1generated · all · 0.2.0.377349Static0.5172.563.13—34242771
anymal_1source · all · 0.2.0.377349Static0.1082.573.44—39563583
anymal_64generated · all · 0.2.0.377349Static0.9932.943.32—35242754
anymal_64source · all · 0.2.0.377349Moving / CUDA0.79041.0753.7821.9235053238
anymal_64source · rendering · 0.2.0.377349Moving / CUDA0.21441.3849.7722.5635203237
anymal_marble_1generated · all · 0.2.0.377349Static0.4822.703.60—34002706
anymal_marble_1source · all · 0.2.0.377349Static0.1882.793.43—35902870
cartpole_1generated · all · 0.2.0.377349Static0.0313.163.71—33862642
cartpole_1source · all · 0.2.0.377349Static0.0522.773.51—34603173
franka_1generated · all · 0.2.0.377349Static0.4782.863.96—33952644
franka_1source · all · 0.2.0.377349Static0.0843.854.52—34713174
anymal_64source · all · 0.2.0.378985Moving / CUDA0.49445.9360.0124.3865363518
anymal_64source · all · 0.2.0.378985Moving / CPU0.50742.4851.2221.9035103237
Table 8. All 13 OVRTX 0.5 research runs; p95 is the 95th percentile of frame time.

Static rows reuse a committed update. Moving rows write 1,088 transforms each frame; frame time includes publication. A static reconstructed scene is not a moving-scene baseline. Population excludes renderer creation and Newton import. CPU is resident process memory; GPU is a dedicated-allocation snapshot. MiB denotes 2²⁰ bytes. Download measurement data (CSV).

Release the viewer upgrade after its functional checks. Qualify Isaac Lab separately: repeated timing with physics, peak CPU/GPU memory, cloning, multiple cameras and matched Kit captures. These establish the workload limits.

Sources, prototype code and reproduction