Extension: omni.kit.scene_view.xr_utils-1.0.2 |
Documentation Generated: Jul 18, 2026 |
Spatial Sources#
A SpatialSource is one transform
contribution in the placement of a
UiContainer. Each source produces a
single omni.ui.scene.Transform node; a list of sources — passed as the
space_stack argument to UiContainer — produces a chain of transforms
applied left-to-right (outer-to-inner).
container = UiContainer(
scene_view_type=XRSceneView,
initial_component=panel_component,
space_stack=[
SpatialSource.new_translation_source(Gf.Vec3f(0.0, 170.0, -60.0)),
SpatialSource.new_look_at_camera_source(),
],
)
The list above first translates to a world position, then rotates the panel to face the camera around that pivot — the classic billboard HUD pattern. Re-order the list, and the camera rotation would happen first and the translation would be interpreted in the rotated frame.
You do not subclass SpatialSource directly in normal use; instead, you call
one of the static factory methods listed below. Each returns a fully-built
SpatialSource you can hand to a UiContainer.
new_translation_source(position)#
Apply a fixed translation in stage units (typically centimetres).
SpatialSource.new_translation_source(Gf.Vec3f(0.0, 150.0, -80.0))
# Move 1.5 m up and 80 cm in front of whatever pivot precedes it.
The translation combines with sibling sources; if it is the first source in the stack, it is interpreted in world space.
new_rotation_source(euler)#
Apply a fixed Euler-angle rotation. The vector is passed straight through to
omni.ui.scene.Matrix44.get_rotation_matrix, which interprets the components
as rotations around X, Y, and Z in degrees by default.
SpatialSource.new_rotation_source(Gf.Vec3f(0.0, 45.0, 0.0)) # yaw 45°
For runtime-driven rotation, drive the manipulator directly (see
container.manipulator.rotation_degrees) or feed a matrix through
new_transform_matrix_source below.
new_scale_source(scale)#
Apply a per-axis scale factor. Pass equal values on all three axes for a uniform scale, or differing values to stretch the panel non-uniformly:
SpatialSource.new_scale_source(Gf.Vec3f(1.5, 1.5, 1.5)) # 1.5× uniform
SpatialSource.new_scale_source(Gf.Vec3f(2.0, 1.0, 1.0)) # wide aspect
Note that scaling a panel does not improve its rendered fidelity — the
underlying texture resolution is set by WidgetComponent and stays fixed
under scaling. Adjust resolution_scale on the component instead if a scaled
panel looks soft.
new_look_at_camera_source()#
Rotate the panel to face the view camera every frame. In XR this tracks the headset’s view. The source contributes rotation only, leaving translation inherited from preceding sources — so place a translation or prim-path source before this one to position the pivot in world space.
space_stack = [
SpatialSource.new_translation_source(Gf.Vec3f(0.0, 170.0, -60.0)),
SpatialSource.new_look_at_camera_source(),
]
new_prim_path_source(prim_path)#
Anchor the UI to a USD prim’s world transform. The source samples the prim’s local-to-world transform every frame, so the UI tracks the prim’s motion in the stage.
SpatialSource.new_prim_path_source("/World/Robot/Head")
This source sets the full world transform of its Transform node, which
means it overrides any translation, rotation, or scale that came before it in
the stack. Stack additional offsets after it to apply relative motion:
space_stack = [
SpatialSource.new_prim_path_source("/World/Robot/Head"), # anchor
SpatialSource.new_translation_source(Gf.Vec3f(0.0, 30.0, 0.0)), # lift 30 cm
SpatialSource.new_look_at_camera_source(), # face viewer
]
The path can be a Python str or an Sdf.Path. If the prim does not exist
when the container is built, the transform will track it as soon as the prim
appears — but the source itself does not poll; it relies on the underlying
omni.kit.scene_view.xr.XRPrimPathTransformBasis to update.
new_transform_matrix_source(matrix)#
The escape hatch. Pass any USD Gf.Matrix4f or Gf.Matrix4d; it is applied
verbatim. Useful when you have an existing transform from elsewhere in the
application and want to drop it into the stack without decomposing it into
translation / rotation / scale parts.
SpatialSource.new_transform_matrix_source(my_gf_matrix)
For runtime-mutable matrices, build the source once and reach into
source.source to swap the backing SpatialSourceBase, or rebuild the
container when the matrix changes infrequently.
Composition order matters#
The stack is applied left-to-right (outer-to-inner). Two rules cover most cases:
Sources that contribute relative transforms — translation, rotation, scale, matrix, look-at — combine with whatever preceded them.
The prim-path source overrides preceding contributions, because it sets the full world transform of the underlying
Transformnode.
That asymmetry produces two common patterns:
# Billboard HUD anchored to a world point.
[translation, look_at_camera]
# Billboard label that follows a prim, lifted above its origin.
[prim_path, translation, look_at_camera]
If a panel ends up in an unexpected place, reorder the stack so the anchoring source comes first and any relative offsets follow.
Edge cases#
Per-frame sampling.
look_at_cameraandprim_pathsources sample the camera and the stage every frame.Missing prims. A prim-path source whose target does not yet exist will produce an identity transform until the prim is added; the source picks the prim up automatically on the next sample.
Reordering at runtime.
space_stackis read once during construction. To change the placement strategy of an existing container, either reach into thesourcesetter on individual sources (for like-for-like swaps) or rebuild the container.
See also#
SpatialSource— the class itself, including the constructor for customSpatialSourceBasesubclasses.WidgetComponent — what the sources position.
Examples —
02_camera_facing_ui.pyexerciseslook_at_camera;03_prim_anchored_ui.pyexercisesprim_pathtogether with translation andlook_at_camerato demonstrate composition.