Omniverse Realtime Viewer
NVIDIAOfficialCreated by NVIDIA Omniverse
- Skill
- Tool integration
- Software development
- Apache-2.0
- Medium risk
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The Omniverse Realtime Viewer skill acts as a central routing and architectural framework for developing USD-based 3D viewer applications. It provides a structured approach to composing rendering, scene state, and delivery mechanisms, ensuring that developers can integrate OVRTX rendering, OVStage scene management, and various UI or streaming adapters effectively. The skill emphasizes a modular architecture where the viewer runtime, UI/input adapters, and delivery systems are decoupled, allowing for consistent behavior across local and streamed environments.
What it does
- Provides a routing architecture for USD viewer apps, XR delivery, and GPU-accelerated rendering.
- Defines the separation of concerns between viewer runtime, UI adapters, and delivery systems.
- Offers guidance on integrating OVRTX for high-fidelity 3D rendering.
- Establishes conventions for camera interaction, scene state management, and input handling.
- Supports the implementation of specialized features like stylized rendering and CAE/CFD visualization.
- Provides protocols for agent-to-UI communication and scene control.
When to use it
- When starting the development of a new USD-based realtime viewer application.
- When integrating advanced rendering features like stylized visualization or AOV switching.
- When building XR or spatial editing capabilities into an existing Omniverse application.
- When you need to standardize the architecture for local and streamed viewer deployments.
- When implementing chat-driven scene control or agent-based inspection of a 3D scene.
Advantages
- Promotes a clean, modular architecture that separates rendering logic from UI and transport.
- Ensures consistent behavior across different delivery methods, such as local windows or WebRTC streaming.
- Provides clear paths for extending functionality without disrupting the core viewer runtime.
- Facilitates the integration of complex simulation and visualization data into the viewer.
- Standardizes conventions for scene state, selection, and camera control.
Usage examples
- “How do I set up a basic USD viewer application using the Omniverse Realtime Viewer architecture?”
- The agent will guide you to start with the viewer app reference, resolve dependencies, and implement the core runtime owner to manage the OVStage and OVRTX renderer.
- “I need to add stylized rendering to my existing viewer. Where should I start?”
- The agent will direct you to the stylized visualization references to implement the required USD/Lua/CUDA nodes within your existing runtime owner.
- “How can I enable an AI agent to control the viewer scene?”
- The agent will point to the A2UI Scene Copilot reference to implement an operation interface that allows the agent to send commands through the existing runtime owner.
- “How do I switch between different render outputs like beauty and depth in my viewer?”
- The agent will explain how to use the AOV switching reference to map RenderVars and update the RenderProduct's orderedVars through the runtime owner.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/nvidia/omniverse-realtime-viewer/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip omniverse-realtime-viewer.zip -d .agents/skills
Documentation by NVIDIA Omniverse
<!-- SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -->
<!-- SPDX-License-Identifier: Apache-2.0 -->
Omniverse Realtime Viewer
Build responsive USD viewers by composing OVRTX rendering, OVStage scene state, and the delivery/UI libraries appropriate to the app. Use this package for viewer architecture and interaction; use each selected SDK's upstream guidance for installation and exact release-specific APIs.
Start With The App
When delivery is explicit, select its recipe through
references/routing.mdand follow its current phase. Otherwise start withreferences/usd-viewer-app/README.md. For an existing app, keep its architecture and read only the references for the requested change. Broad app, conventions and UI catalogs are lookups as needed.Resolve the selected libraries through
references/dependencies/README.md. Preserve the project's manifest unless an upgrade is requested.Build a working frame and camera interaction in the chosen shell, then add the requested capabilities. Read
references/conventions.mdfor shared input, camera, selection, and protocol conventions.Use
references/viewer-ux-workflow/README.mdfor broader interface design. Loading, selection feedback, errors, and input responsiveness belong in the first working app, alongside rendering.Validate the actual delivery path with
references/validation.md. A browser screenshot does not validate a native window or a different transport.
Architecture
| Owner | Responsibility |
|---|---|
| Viewer runtime | Own the live OVStage, publication clock, OVRTX renderer, scene changes, and render stepping. |
| UI and input adapter | Display frames and copied app state; send user intent to the runtime owner. |
| Storage/query/simulation workers | Perform their assigned work and return results through the selected integration boundary. |
| Delivery adapter | Present locally or stream through ovstream; respect frame ownership and backpressure. |
Use OVRTX for USD/3D rendering. Browser apps display its WebRTC video; local apps present its output through their native shell. A missing GPU means rendering is unverified, not a reason to substitute a browser 3D renderer.
Keep viewer cameras, settings, effects, and transient edits in app-owned session
or runtime state so the source USD stays intact. Serialize scene mutation and
render stepping through the runtime owner. Read
references/ovstage-ovrtx-integration/README.md for that loop, then the population
or data-plane references when implementing scene loading or attribute writes.
Keep expensive loading and metadata work off the UI and render threads. Keep transport details behind a delivery adapter so camera, selection, properties, and loading state can be reused across local and streamed shells.
Add Capabilities As Needed
Use references/routing.md to select camera/picking, scene management, render
settings, cloud assets, simulation, editor tools, deployment, or CAE/CFD
visualization. Read the selected capability's implementation flow and its linked
contract; the full reference catalog is not a prerequisite for a first frame.
For simulation, use the routing reference's Simulation Ecosystem section plus
references/realtime-sim-integration/README.md. For UI-driven forces or control,
add references/interaction-round-trip/README.md.
For example scenes, use references/usd-sample-data/README.md. When a runtime
failure needs diagnosis, use references/troubleshooting/README.md and the
selected SDK's matching release guidance before changing the architecture.
Solid Modeling: Upstream First
For usd-brep, exact BRep, solid modeling, kernel failures, CAD topology, or
BrepArray questions, first read references/dependencies/README.md → USD BRep. Follow the
owning repository's current agent guidance, skills, operation docs, and package
API before selecting local integration references. Discover the upstream router
rather than assuming skill names or directory layouts remain fixed. Upstream
owns modeling semantics, schema rules, tuning, and diagnostics; this package
owns OVRTX display, worker handoff, selection mapping, and publication timing.
GPU Processing And Stylized Viewers
For custom GPU processing, chained outputs and lens sampling, read
references/spg-processing/README.md. For toon, ink, technical/X-Ray styles,
geometry strokes or full wireframe, continue to
references/stylized-visualization/implementation.md. Its USD/Lua/CUDA starting
node and geometry/depth/composite build sequence work with the selected viewer
recipe; use references/stylized-visualization/style-recipes.md for the preset
math and references/stylized-visualization/README.md for supporting contracts.
Implement the result inside the existing OVRTX/runtime owner and deliver the
published processed output. These instructions do not require a sample checkout
or a prior stylized-rendering implementation.
For an optional usd-brep geometry source, first read
references/dependencies/README.md → USD BRep and the owning repository's
current agent guidance, skills, and operation docs; then read
references/stylized-visualization/usd-brep-source.md for the display boundary.
XR Viewers
For headsets, immersive viewers, or spatial editors, start with
references/xr-viewer-recipe/README.md. Resolve SDK setup and contracts through
references/dependencies/ovxr.md; the library owns OpenXR lifecycle and frame
submission. For controllers, hands, navigation, or scene tools, add
references/xr-spatial-input/README.md and
references/ovxr-python-interactions/README.md. For projection-integrated UI,
read references/ovxr-composition-ui/README.md and
references/ovxr-composition-ui-validation/README.md.
Files
- ATTRIBUTION.mdAdded by AutoGineer943 B
- BENCHMARK.md13.4 KiB
- LICENSELicence file added by AutoGineer11.2 KiB
- SKILL.md6.4 KiB
- evals/evals.json7.0 KiB
- references/a2ui-scene-copilot/README.md10.9 KiB
- references/aov-switching/README.md10.5 KiB
- references/cae-cfd-visualization/README.md10.1 KiB
- references/cae-cfd-visualization/cae-data-ingestion.md5.6 KiB
- references/cae-cfd-visualization/coordinate-systems-and-up-axis.md11.0 KiB
- references/cae-cfd-visualization/data-and-operators.md11.7 KiB
- references/cae-cfd-visualization/driving-cae-viz-via-ovstage.md6.4 KiB
- references/cae-cfd-visualization/emitter-and-seed-sources.md16.3 KiB
- references/cae-cfd-visualization/glyphs.md7.1 KiB
- references/cae-cfd-visualization/ovstage-render-and-camera.md11.0 KiB
- references/cae-cfd-visualization/ovui-controls.md13.2 KiB
- references/cae-cfd-visualization/rtwt-blueprint-recreation.md11.9 KiB
- references/cae-cfd-visualization/streaming-cae-viewer.md25.9 KiB
- references/cae-cfd-visualization/temporal-playback.md9.2 KiB
- references/cae-cfd-visualization/usd-authoring-and-materials.md21.5 KiB
- references/cae-cfd-visualization/volume-rendering.md2.5 KiB
- references/camera-auto-select/README.md9.0 KiB
- references/camera-controls/README.md20.9 KiB
- references/camera-picker/README.md9.5 KiB
- references/cloud-assets/README.md4.5 KiB
- references/cloud-deployment/README.md19.6 KiB
- references/cloud-deployment/container-image-build.md2.2 KiB
- references/cloud-deployment/gpu-container-runtime.md2.8 KiB
- references/cloud-deployment/nvcf-self-hosted.md8.4 KiB
- references/cloud-deployment/nvcf-viewer-container-contract.md4.8 KiB
- references/cloud-deployment/webrtc-network-diagnostics.md3.9 KiB
- references/cloudxr-opaque-data-channel/README.md1.1 KiB
- references/conventions.md7.4 KiB
- references/cpp-native-viewer/README.md4.9 KiB
- references/cpp-native-viewer/build-details.md5.2 KiB
- references/cpp-native-viewer/interaction-features.md11.3 KiB
- references/cpp-native-viewer/presentation-loop.md8.0 KiB
- references/cpp-native-viewer/project-build.md3.4 KiB
- references/cpp-native-viewer/renderer-session.md7.1 KiB
- references/cpp-native-viewer/validation.md3.4 KiB
- references/dependencies/README.md6.8 KiB
- references/dependencies/electron-shm.md1.5 KiB
- references/dependencies/environment-validation.md6.6 KiB
- references/dependencies/frontend.md2.3 KiB
- references/dependencies/local-openusd-gpu.md8.7 KiB
- references/dependencies/nvidia-runtime.md14.8 KiB
- references/dependencies/ovrtx.md3.1 KiB
- references/dependencies/ovstream.md3.3 KiB
- references/dependencies/ovxr.md2.3 KiB
- references/dependencies/quick-setup.md2.6 KiB
- references/dependencies/skia-yoga.md936 B
- references/electron-shm-viewer/README.md2.5 KiB
- references/electron-shm-viewer/architecture-project.md6.3 KiB
- references/electron-shm-viewer/electron-client.md6.5 KiB
- references/electron-shm-viewer/protocol-interaction-lifecycle.md7.9 KiB
- references/electron-shm-viewer/python-shm-server.md5.5 KiB
- references/electron-shm-viewer/validation.md2.8 KiB
- references/exact-brep-in-usd/README.md2.5 KiB
- references/gl-viewport-overlay/README.md8.0 KiB
- references/gl-viewport-overlay/architecture.md4.1 KiB
- references/gl-viewport-overlay/example-gizmo.md5.5 KiB
- references/gl-viewport-overlay/interaction-pattern.md4.0 KiB
- references/gl-viewport-overlay/projection-alignment.md4.3 KiB
- references/headless-shm-cli/README.md12.3 KiB
- references/huggingface-usd/README.md7.7 KiB
- references/interaction-round-trip/README.md40.1 KiB
- references/local-viewer/README.md17.8 KiB
- references/native-picking-selection/README.md13.1 KiB
- references/navigation-presets/README.md4.6 KiB
- references/navigation-presets/preset-camera-ops.md5.1 KiB
- references/newton-physics/README.md8.8 KiB
- references/object-selection/README.md11.1 KiB
- references/ovrtx-rendering/README.md23.0 KiB
- references/ovstage-data-plane/README.md3.5 KiB
- references/ovstage-live-geometry/README.md3.3 KiB
- references/ovstage-ovrtx-integration/README.md5.0 KiB
- references/ovstage-population/README.md3.7 KiB
- references/ovstage-runtime/README.md3.1 KiB
- references/ovui-library/README.md3.3 KiB
- references/ovui-library/api-reference.md4.3 KiB
- references/ovui-library/extending.md4.8 KiB
- references/ovui-local-viewer-recipe/README.md4.7 KiB
- references/ovui-local-viewer-recipe/interaction-features.md16.9 KiB
- references/ovui-local-viewer-recipe/project-structure.md6.2 KiB
- references/ovui-local-viewer-recipe/setup-shell-renderer.md16.4 KiB
- references/ovui-local-viewer-recipe/validation-build-order.md6.1 KiB
- references/ovwidgets-editor-shell/README.md5.4 KiB
- references/ovxr-composition-ui-validation/README.md7.1 KiB
- references/ovxr-composition-ui-validation/evidence-gates.md3.5 KiB
- references/ovxr-composition-ui-validation/frustum-placement.md2.4 KiB
- references/ovxr-composition-ui-validation/library-only-validation.md8.1 KiB
- references/ovxr-composition-ui-validation/owned-orchestration.md5.3 KiB
- references/ovxr-composition-ui-validation/viewer-evidence.md4.0 KiB
- references/ovxr-composition-ui/README.md8.5 KiB
- references/ovxr-composition-ui/async-raster-pipeline.md5.0 KiB
- references/ovxr-composition-ui/compositor-passes-and-sync.md6.4 KiB
- references/ovxr-composition-ui/depth-tools.md5.0 KiB
- references/ovxr-composition-ui/editor-document-model.md4.8 KiB
- references/ovxr-composition-ui/experience-quality.md8.5 KiB
- references/ovxr-composition-ui/foveation-and-edge-math.md3.5 KiB
- references/ovxr-composition-ui/library-only-compositor.md10.4 KiB
- references/ovxr-composition-ui/native-build-and-discovery.md4.6 KiB
- references/ovxr-composition-ui/performance-and-telemetry.md7.9 KiB
- references/ovxr-composition-ui/primary-projection-compositor.md3.5 KiB
- references/ovxr-composition-ui/primary-projection.md4.1 KiB
- references/ovxr-composition-ui/projection-and-depth.md5.3 KiB
- references/ovxr-composition-ui/raster-abi.md3.0 KiB
- references/ovxr-composition-ui/sdk-frame-backend.md1.6 KiB
- references/ovxr-composition-ui/skia-yoga.md2.8 KiB
- references/ovxr-composition-ui/spatial-interaction.md5.6 KiB
- references/ovxr-composition-ui/spatial-surfaces-and-interaction.md10.4 KiB
- references/ovxr-composition-ui/telemetry-contract.md3.8 KiB
- references/ovxr-composition-ui/validation-and-live-gates.md3.9 KiB
- references/ovxr-foveation-and-display/README.md1.1 KiB
- references/ovxr-frame-loop-and-readback/README.md1.2 KiB
- references/ovxr-library-runtime/README.md1.1 KiB
- references/ovxr-library-runtime/ar-compositing.md4.4 KiB
- references/ovxr-library-runtime/frame-input-order.md2.2 KiB
- references/ovxr-library-runtime/library-only.md1.1 KiB
- references/ovxr-library-runtime/live-ar-controls.md4.3 KiB
- references/ovxr-library-runtime/mirror-lifetime.md4.1 KiB
- references/ovxr-library-runtime/settings-and-lifetime.md3.9 KiB
- references/ovxr-library-runtime/viewer-assembly.md225 B
- references/ovxr-openxr-runtime/README.md1012 B
- references/ovxr-python-interactions/README.md1.8 KiB
- references/ovxr-python-interactions/architecture.md5.5 KiB
- references/ovxr-python-interactions/feature-patterns.md7.4 KiB
- references/physics-simulation/README.md7.1 KiB
- references/prim-info-display/README.md10.9 KiB
- references/prim-pick-effects/README.md7.3 KiB
- references/prim-transform-safety/README.md8.6 KiB
- references/realtime-sim-integration/README.md7.0 KiB
- references/render-settings/README.md12.6 KiB
- references/routing.md37.7 KiB
- references/section-views/README.md5.8 KiB
- references/seg-outline-highlight/README.md1.5 KiB
- references/selection-animation/README.md5.0 KiB
- references/selection-feedback/README.md7.5 KiB
- references/smlib-brep-pitfalls/README.md2.5 KiB
- references/spg-processing/README.md8.0 KiB
- references/stage-attribute-reads/README.md6.2 KiB
- references/stage-hierarchy/README.md20.3 KiB
- references/stage-hierarchy/fallback-worker-protocol.md7.4 KiB
- references/stage-loading/README.md7.1 KiB
- references/stage-management/README.md6.6 KiB
- references/stage-queries/README.md6.1 KiB
- references/streaming-client/README.md25.6 KiB
- references/streaming-lifecycle/README.md4.6 KiB
- references/streaming-messages/README.md19.5 KiB
- references/streaming-messages/server-handler-map.md3.1 KiB
- references/streaming-server/README.md17.7 KiB
- references/streaming-server/frame-loop-and-continuity.md3.8 KiB
- references/streaming-viewer-recipe/README.md1.9 KiB
- references/streaming-viewer-recipe/client-protocol.md14.2 KiB
- references/streaming-viewer-recipe/interaction-features.md13.8 KiB
- references/streaming-viewer-recipe/project-structure.md7.3 KiB
- references/streaming-viewer-recipe/server-runtime.md20.2 KiB
- references/streaming-viewer-recipe/validation-build-order.md8.5 KiB
- references/streaming-vs-local/README.md9.4 KiB
- references/stylized-visualization/README.md8.7 KiB
- references/stylized-visualization/aov-guide-contracts.md8.1 KiB
- references/stylized-visualization/implementation.md11.4 KiB
- references/stylized-visualization/line-compositor-delivery.md7.7 KiB
- references/stylized-visualization/mesh-xray.md10.1 KiB
- references/stylized-visualization/reproduction-validation.md10.2 KiB
- references/stylized-visualization/style-composition-contract.md5.4 KiB
- references/stylized-visualization/style-recipes.md14.7 KiB
- references/stylized-visualization/usd-brep-source.md4.9 KiB
- references/subprocess-geometry-bridge/README.md3.5 KiB
- references/tauri-local-viewer/README.md6.7 KiB
- references/tauri-shm-transform-gizmo/README.md12.3 KiB
- references/transform-manipulator/README.md17.1 KiB
- references/troubleshooting/README.md11.2 KiB
- references/troubleshooting/scenario-playbooks.md24.7 KiB
- references/usd-sample-data/README.md12.0 KiB
- references/usd-viewer-app/README.md5.0 KiB
- references/validation.md6.3 KiB
- references/viewer-backend-interface/README.md20.1 KiB
- references/viewer-control-patterns/README.md4.8 KiB
- references/viewer-data-view-patterns/README.md5.6 KiB
- references/viewer-feedback-status/README.md5.0 KiB
- references/viewer-input-routing/README.md11.9 KiB
- references/viewer-layout-patterns/README.md4.7 KiB
- references/viewer-ux-workflow/README.md5.2 KiB
- references/viewport-overlays/README.md9.9 KiB
- references/viewport-overlays/cuda-compositing.md6.6 KiB
- references/viewport-resize/README.md4.0 KiB
- references/vulkan-compositing/README.md6.1 KiB
- references/vulkan-compositing/depth-overlays.md15.7 KiB
- references/vulkan-compositing/interop-and-lifecycle.md6.6 KiB
- references/webgl-shm-transport/README.md14.5 KiB
- references/windows-native-setup/README.md11.6 KiB
- references/xr-client-connection/README.md1.1 KiB
- references/xr-client-message-contract/README.md8.5 KiB
- references/xr-desktop-mirror/README.md13.8 KiB
- references/xr-session-modes-and-passthrough/README.md930 B
- references/xr-spatial-input/README.md2.3 KiB
- references/xr-spatial-input/advanced-tools.md5.2 KiB
- references/xr-spatial-input/controllers.md16.3 KiB
- references/xr-spatial-input/feature-validation.md4.9 KiB
- references/xr-spatial-input/gesture-arbitration.md4.9 KiB
- references/xr-spatial-input/gesture-filtering.md5.5 KiB
- references/xr-spatial-input/hand-recognizers.md4.0 KiB
- references/xr-spatial-input/hands.md10.3 KiB
- references/xr-spatial-input/navigation.md13.5 KiB
- references/xr-spatial-input/physics-interaction.md23.2 KiB
- references/xr-spatial-input/simulation-lifecycle.md5.9 KiB
- references/xr-spatial-input/stage-composition.md4.9 KiB
- references/xr-spatial-input/teleport-acceptance.md5.2 KiB
- references/xr-spatial-input/webxr-client.md3.9 KiB
- references/xr-tracking-anchor-and-scale/README.md950 B
- references/xr-viewer-recipe/README.md10.5 KiB
- skill-card.md7.7 KiB
- skill.oms.sig58.2 KiB
references/transform-manipulator/README.md
Transform Manipulator
Use this when an Omniverse Realtime Viewer needs interactive translate, rotate,
or scale controls for a selected USD prim. Also read ovstage-data-plane for
runtime transform writes, prim-transform-safety for live local/world transforms
and reset-stack inheritance. Use viewport-overlays when choosing server-side
ovui composition. For application-parameter manipulators such as section planes,
read section views.
For ovui-owned gizmo, widget, or headless overlay behavior beyond this skill,
read references/dependencies for acquisition guidance and supplemental dependency
documentation.
Implementation Contract
Implement these pieces in the generated app as needed:
Local ovui frame gizmo: draw translate, rotate, and scale handles directly into the numpy RGBA frame before
ByteImageProviderreceives it.Viewport input router: convert letterboxed viewport coordinates into render coordinates and give the gizmo pointer priority before camera controls.
App tool state: own active tool, keyboard shortcuts, toolbar state, selected path synchronization, animation pause/resume, and pending transform updates.
Runtime bridge: write live
omni:xformvalues through OVStage for immediate renderer feedback, then optionally commit final persistent edits through the selected session-layer path.Optional WebRTC headless overlay: draw the same manipulator grammar through ovui overlay primitives, then alpha-composite the RGBA overlay over the streamed BGRA frame.
Message/input handler: route pointer and keyboard input to the gizmo first, then to camera or selection handlers only when the gizmo does not consume it.
Shared projection helper: expose one
world_to_screen()convention for headless overlays, hit testing, labels, and tooltips.Server-composited presentation only: blend overlay RGBA over the ovrtx BGRA stream buffer without copying the full video frame through browser-side 3D rendering.
Architecture
Choose a presentation path while sharing interaction state and projection math: target identity, active tool, projected handles, hit testing, and drag state. Prim targets additionally share OVStage transform writes and optional USD/session authoring; parameter targets share their owner-applied parameter model.
WebRTC path:
ovrtx renderer.step() -> LdrColor CUDA frame
-> headless ovui TransformGizmoOverlay draws SceneView primitives
-> copy ovui RGBA output to CUDA
-> CUDA alpha blend over BGRA stream buffer
-> ovstream WebRTC video frame
Local ovui path:
ovrtx renderer.step() -> CPU numpy RGBA frame
-> TransformGizmo.draw(frame) draws anti-aliased lines/polygons
-> ImageBridge.update(frame) -> ByteImageProviderA WebRTC viewer may instead draw 2D SVG/canvas/DOM handles over the video.
Project them from authoritative camera/target state and align them with the
visible image rectangle. These are UI overlays: scene geometry, materials, and
section caps continue to render through OVRTX. Use a server-composited overlay
when handles must appear in the encoded frame. For Tauri SHM, also read
tauri-shm-transform-gizmo for its platform-specific input lifecycle.
A parameter gizmo emits plane/light/tool intent to the owner; it need not select
or mutate a USD prim. Reuse projection, drag snapshots, cancellation, and input
priority without forcing parameter edits through the prim-transform protocol.
See viewer-input-routing for browser overlay gesture ownership.
Input Priority
The gizmo must receive mouse input before the camera controller. If the camera sees the press first, orbit steals the drag and the manipulator feels broken.
def on_mouse_pressed(x, y, button, modifier):
local = viewport_to_render_coords(x, y, clamp=False)
if local and transform_gizmo.mouse_pressed(local[0], local[1], button):
camera_dragging = False
return
mapped = camera_button_from_ovui(button)
if mapped is not None:
lx, ly = viewport_to_render_coords(x, y, clamp=True)
camera.on_mouse_button_down(lx, ly, mapped)During drag, keep routing all move and release events to the gizmo, even when the pointer leaves the rendered image. Clamp coordinates while dragging so release can finish cleanly.
def on_mouse_moved(x, y):
dragging = bool(getattr(transform_gizmo, "dragging", False))
local = viewport_to_render_coords(x, y, clamp=dragging)
if local and transform_gizmo.mouse_moved(local[0], local[1]):
return
if camera_dragging:
camera.on_mouse_move(*viewport_to_render_coords(x, y, clamp=True))For server-composited WebRTC/headless overlays, the server input bridge follows the same rule: transform_gizmo.handle_input(event) runs before camera input dispatch, and returns True when the gizmo consumed the event.
In lightweight local ovui shells, do not assume that drawing a SceneView gizmo
also wires low-level handle drag events into the application. If the selected
handle/pivot can be hit but no transform callback fires, add an app-owned
fallback: project the selected prim pivot into the visible image rect, treat an
LMB press within a generous radius as transform intent, and route the whole
mouse-down to the transform model. The release must not also enqueue a pick.
Hit Testing
Project the gizmo origin and each world-axis tip to screen space every frame:
AXES = {
"x": np.array([1.0, 0.0, 0.0]),
"y": np.array([0.0, 1.0, 0.0]),
"z": np.array([0.0, 0.0, 1.0]),
}
HIT_RADIUS_PX = 35.0
AXIS_LENGTH_PX = 88.0
RING_RADII_PX = {"x": 76.0, "y": 64.0, "z": 52.0}For translate and scale, choose the closest axis line segment from center to tip.
def distance_to_segment(point, start, end):
segment = end - start
denom = float(np.dot(segment, segment))
if denom <= 1e-9:
return float(np.linalg.norm(point - start))
t = np.clip(np.dot(point - start, segment) / denom, 0.0, 1.0)
return float(np.linalg.norm(point - (start + segment * t)))
hit = min(axis_cache, key=lambda item: distance_to_segment(point, origin, item.end))
axis = hit.name if hit.distance <= HIT_RADIUS_PX else NoneFor rotate, compare the click radius to the ring radii and choose the nearest ring.
distance = float(np.linalg.norm(point - screen_origin))
delta, axis = min(
(abs(distance - radius), axis_name)
for axis_name, radius in RING_RADII_PX.items()
)
return axis if delta <= HIT_RADIUS_PX else NoneChoose hit targets in display pixels for the actual viewport scale and input latency; validate them after resizing. For a near-degenerate projected axis, use a valid alternate interaction constraint or disable it with an explanation. A fabricated screen direction alone does not define a world-space drag.
Projection And Drag Math
Project the axis direction, not only the axis endpoint. Try larger world-space scales until the projected direction has a usable length.
FALLBACK_AXIS_SCREEN = {
"x": np.array([1.0, 0.0]),
"y": np.array([0.0, -1.0]),
"z": np.array([-0.72, 0.52]),
}
def project_axis_direction(origin, world_axis, axis_name):
for scale in (1.0, 10.0, 100.0, 1000.0):
projected = world_to_top_left_screen(origin + world_axis * scale)
if projected is None:
continue
delta = projected - screen_origin
length = float(np.linalg.norm(delta))
if length > 0.5 and math.isfinite(length):
return delta / length, length / scale
fallback = FALLBACK_AXIS_SCREEN[axis_name]
return fallback / np.linalg.norm(fallback), 1.0Drag math is screen-space first. Store the starting transform and compute each update from that base; do not accumulate small increments frame-to-frame.
delta_px = float(np.dot(mouse - drag.start_mouse, drag.screen_direction))
if drag.tool == "translate":
amount = delta_px / max(drag.pixels_per_world_unit, 1e-6)
next_position = drag.start_position + AXES[drag.axis] * amount
next_transform = drag.start_transform.copy()
next_transform[3, :3] = next_position
elif drag.tool == "rotate":
next_transform = rotate_transform(
drag.start_transform,
AXES[drag.axis],
delta_px * 0.01, # radians
)
elif drag.tool == "scale":
factor = max(0.05, 1.0 + delta_px / 140.0)
next_transform = scale_transform(drag.start_transform, drag.axis, factor)The viewer matrix convention is row-major with translation in row 3. Keep world_to_screen() coordinate conventions consistent: if the projection helper returns bottom-left origin, convert once to top-left origin before hit testing.
Runtime Transform Handoff And USD Commit
The manipulator contributes local matrices to the runtime owner's existing tick. Snapshot the selected prim's live local and world transforms at drag start, then compute each drag sample from that base. Convert world intent through the current reset-aware effective parent from prim transform safety.
import numpy as np
def resolve_drag_transform(runtime, path: str, world_transform: np.ndarray) -> np.ndarray:
# App-owned adapter: identity for a reset-stack target, otherwise the
# current parent world matrix composed from runtime ancestor locals.
parent_world = runtime.read_effective_parent_transform(path)
local = np.asarray(world_transform, dtype=np.float64) @ np.linalg.inv(parent_world)
return localPointer callbacks enqueue world intent with the stage generation. The runtime
owner calls this resolver using its current transform snapshot. Reject a
singular parent and report the edit failure. Adapter methods belong to the
application; a pointer callback must not read stage data, allocate an ordinal,
or render. The resolved locals join camera, animation, and other interaction
updates in the owner's batch.
The owner writes the final local matrices with the
write_local_transforms helper,
using AttributeSemantic.MATRIX, PrimMode.UPSERT, and one 16-lane float64
element per queried prim. It publishes once after the tick's writes complete,
then renders that ordinal. Do not use standalone OVRTX attribute APIs to mutate
an attached OVStage.
Session-layer xformOp authoring is useful for persistent/editor-style edits,
but it should not be the only path for a realtime viewer drag. If both are
required, write live omni:xform through OVStage during the drag and commit the
final edit through the chosen session-layer/undo path on release.
Author optional persistent manipulator edits into the session layer so user USD files remain non-destructive. Commit the accepted local matrix from the runtime transform model; do not recompute it from a stale authored parent in a USD worker. Preserve the target's reset-stack state when authoring the corresponding ops.
from pxr import Gf, Usd, UsdGeom
def apply_local_transform_to_prim(stage, path, local_transform):
prim = stage.GetPrimAtPath(path)
if not prim or not prim.IsValid() or not prim.IsA(UsdGeom.Xformable):
return False
local = gf_matrix_from_numpy(local_transform)
translate, rotate_xyz, scale = decompose_common_matrix(local)
with Usd.EditContext(stage, stage.GetSessionLayer()):
return write_xform_ops(UsdGeom.Xformable(prim), translate, rotate_xyz, scale)Write xform ops directly. Do not use UsdGeom.XformCommonAPI.SetRotate() for mixed assets because existing prims may have Gf.Vec3d rotate/scale attributes while SetRotate() expects Gf.Vec3f.
def set_vec3_op(op, values):
attr = op.GetAttr()
type_name = attr.GetTypeName().cppTypeName if attr else ""
if "Vec3d" in type_name or "double" in type_name:
op.Set(Gf.Vec3d(*values), Usd.TimeCode.Default())
else:
op.Set(Gf.Vec3f(*[float(v) for v in values]), Usd.TimeCode.Default())
def write_xform_ops(xformable, translate, rotate_xyz, scale):
ops = {op.GetOpName(): op for op in xformable.GetOrderedXformOps()}
t_op = ops.get("xformOp:translate") or xformable.AddTranslateOp()
r_op = ops.get("xformOp:rotateXYZ") or xformable.AddRotateXYZOp()
s_op = ops.get("xformOp:scale") or xformable.AddScaleOp()
t_op.Set(Gf.Vec3d(*translate), Usd.TimeCode.Default())
set_vec3_op(r_op, rotate_xyz)
set_vec3_op(s_op, scale)
return TrueUse the same transform model to refresh the inspector and gizmo after each
accepted edit. Discard queued edits and cached transforms on a stage-generation
change. See prim-transform-safety for baseline, ancestry, and restoration rules.
Drawing
Use the same visual grammar in both render paths:
X axis: red
(1.0, 0.18, 0.14).Y axis: green
(0.22, 0.92, 0.32).Z axis: blue
(0.25, 0.54, 1.0).Active axis: lighter/brighter variant while dragging.
Translate: axis lines with arrowheads.
Rotate: concentric rings with different radii per axis.
Scale: axis lines with square handles at endpoints.
Center: small white square at the projected origin.
Local frame drawing should alpha-blend anti-aliased line and polygon masks into
the numpy frame. Headless ovui drawing should use omni.ui_scene.scene.Line
and PolygonMesh under the shared overlay SceneView. Implement the
CUDA compositor in the app to blend
the exported RGBA over the BGRA stream; no compositor module is supplied by
this package.
Animation Interaction
Selection animation and manipulator drags share the owner's transform model. The gizmo's transform callback queues world intent for the resolver above. After the owner has composed animation and edits, project the current runtime world transform so handles stay attached to the rendered object, including when an ancestor moves:
world = runtime.read_world_transform(path)
gizmo.set_selection(path, world_transform=world)On drag start, freeze the animation first, then use the current visible runtime
transform as start_transform. On drag end, update the animator base transform
from the final OVStage pose before resuming so it does not snap back to the
pre-drag position.
Tool Selection
Use conventional editor shortcuts and toolbar buttons:
Q = none/select
W = translate
E = rotate
R = scaleThe active tool gates visibility and behavior. No active tool means no manipulator is rendered and no manipulator hit testing should consume camera input.
def set_active_tool(tool):
normalized = None if tool in (None, "", "none", "select") else tool
gizmo.set_active_tool(normalized)
toolbar.set_checked(normalized)For local ovui, wire keyboard shortcuts on the viewport hit rectangle and
toolbar buttons in the header. For WebRTC, send a JSON app message such as
{"event_type": "setActiveTool", "payload": {"tool": "translate"}} and update
the accepted tool state in the chosen overlay presentation.
Common Pitfalls
XformCommonAPI.SetRotate()only acceptsGfVec3f; directly write existing xform ops and preserve their attribute type.Read
viewer-input-routingforovstreammouse button normalization before combining gizmo, camera, and pick handlers.Render-pixel hit radii must scale with the displayed image; test the actual display-space target size.
Hover consumption is intentional:
contains() == Truecan block camera input so the cursor can communicate that the gizmo is interactive. Only start transforms on press hits.Convert viewport coordinates through the same letterbox mapping used for picking and camera input.
Do not call
renderer.step()concurrently with scene reset, OVStage transform publication, or stage mutation.Keep one shared ovui headless overlay window; multiple windows can break frame export.
If an axis projects to near-zero length, use an alternate valid constraint or disable that handle; preserve finite world-space intent.
If the gizmo is visible but the prim stays stationary, verify input ownership first and then verify that the drag callback reaches the OVStage
omni:xformpublication path for the selected prim.
Checklist
[ ] Read
viewport-overlaysfor WebRTC/headless ovui composition orlocal-viewerfor inlineByteImageProviderdrawing.[ ] Read
ovstage-data-planebefore writing liveomni:xformor combining gizmo drags with selection animation.[ ] Route gizmo input before camera input for press, move, release, and wheel.
[ ] Project origin and axes every frame from the current camera view/projection.
[ ] Use
start_transformandstart_mouseas the base for each drag update.[ ] During drag, publish the selected prim's live
omni:xformthrough OVStage; on release, optionally commit to a session-layer USD edit path.[ ] Author USD xform ops in the session layer with parent compensation and Vec3f/Vec3d type preservation.
[ ] Validate with a measured transform delta and OVStage write/render consume ordinal, not only a screenshot of a visible manipulator.
[ ] Freeze animation during drag and resume from the new base transform after drag end.
See also: viewport-overlays, ovstage-data-plane,
ovstage-ovrtx-integration, viewer-input-routing, camera-controls,
object-selection, selection-animation, local-viewer,
streaming-messages.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Python, Needs Node.js
The author says: Orchestrator skill. Downstream focused references may require NVIDIA GPUs, ovrtx, ovstream, ovui, OpenUSD, Python, Node/React, Tauri, Electron, C++, or cloud GPU deployment access depending on the selected viewer path.
Security
What our scanner noticed· Medium risk
- Large base64-encoded blobs
- Instructions that use the network
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- NVIDIA Omniverse
- Publisher
- NVIDIA (Official)
- Source
- NVIDIA/skills · skills/omniverse-realtime-viewer · commit fce3cca
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE-APACHE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by NVIDIA Omniverse or NVIDIA.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download omniverse-realtime-viewer.zip