Writing Transforms#

Transforms are ordinary runtime stage attributes with a transform semantic. The canonical transform attribute is omni:xform. The legacy omni:fabric:localMatrix name is also accepted, but new code should prefer omni:xform.

ovrtx uses the USD row-vector matrix convention: translation is stored in the last row of a 4x4 matrix, at matrix[3][0..2] or flat indices 12..14.

4x4 Matrix Writes#

Python uses NumPy-style tensor shapes. A batch of N 4x4 transforms has shape (N, 4, 4) and dtype float64.

# Back a lane-16 per-prim transform with a 3-D ndarray of shape=(N, 4, 4).
# Translate /World/Camera to (10, 20, 30) using USD row-vector convention
# (translation lives in matrix[3][0..2]).
xform = np.eye(4, dtype=np.float64)
xform[3, 0:3] = [10.0, 20.0, 30.0]
transforms = xform.reshape(1, 4, 4)  # shape=(1, 4, 4)
with ovstage.PathDictionary(stage) as paths:
    path_list = paths.create_path_list_from_strings(["/World/Camera"])
    with stage.query_from_path_list(path_list) as query:
        attribute = paths.intern_token("omni:xform")
        matrix_dtype = ovstage.numpy_to_dldatatype(transforms.dtype, lanes=16)
        matrix_tensor = ovstage.make_dltensor(transforms, dtype=matrix_dtype, shape=[1], ndim=1)
        stage.write_attribute(
            query,
            attribute,
            ordinal=2,
            tensors=matrix_tensor,
            is_array=False,
            semantic=ovstage.AttributeSemantic.MATRIX,
        ).wait()
        stage.advance_write_floor(2, ovstage.Scope.ALL).wait()
        with stage.read_attributes(query, [attribute], ovstage.OrdinalRange.latest(2)) as read:
            group = read.fetch_next()
            values = np.from_dlpack(group.dlpack(0)).copy().reshape(1, 4, 4)
            stage.release_group(group)
        assert values.shape == (1, 4, 4)
    paths.destroy_path_list(path_list)

C convenience helpers in <ovrtx/ovrtx_attributes.h> hide the DLTensor descriptor boilerplate for common transform layouts.

ovx_string_t prim = ovx_str("/World/Plane");
ovrtx_xform_matrix44d_t matrix{};
matrix.v[0] = 1.0;
matrix.v[5] = 1.0;
matrix.v[10] = 1.0;
matrix.v[15] = 1.0;
matrix.v[12] = 5.0;

ovrtx_enqueue_result_t eq = ovrtx_set_xform_mat(renderer_, &prim, 1, &matrix);
ASSERT_API_SUCCESS(eq.status);
docs_wait_no_errors(renderer_, eq.op_index);

C Transform Helpers#

The C API also provides compact helpers for position/rotation/scale layouts and for authoring omni:resetXformStack.

ovx_string_t prim = ovx_str("/World/Plane");
ovrtx_xform_pos3d_rot4f_scale3f_t transform{};
transform.position[0] = 6.0;
transform.rot_quat_xyzw[0] = 1.0f; // 180 degrees around X.
transform.scale[0] = 2.0f;
transform.scale[1] = 3.0f;
transform.scale[2] = 4.0f;

ovrtx_enqueue_result_t eq = ovrtx_set_xform_pos_rot_scale(renderer_, &prim, 1, &transform);
ASSERT_API_SUCCESS(eq.status);
docs_wait_no_errors(renderer_, eq.op_index);
ovx_string_t prim = ovx_str("/World/Plane");
ovrtx_xform_pos3d_rot3x3f_t transform{};
transform.position[0] = 7.0;
transform.rot_matrix[0] = -1.0f;
transform.rot_matrix[4] = -1.0f;
transform.rot_matrix[8] = 1.0f;

ovrtx_enqueue_result_t eq = ovrtx_set_xform_pos_rot3x3(renderer_, &prim, 1, &transform);
ASSERT_API_SUCCESS(eq.status);
docs_wait_no_errors(renderer_, eq.op_index);
ovx_string_t prim = ovx_str("/World/Plane");
bool reset_stack = true;
ovrtx_enqueue_result_t eq = ovrtx_set_reset_xform_stack(renderer_, &prim, 1, &reset_stack);
ASSERT_API_SUCCESS(eq.status);
docs_wait_no_errors(renderer_, eq.op_index);

Repeated Updates#

For per-frame transform animation, avoid rebuilding descriptors on every update:

  • Use Attribute Bindings when the application already owns the transform tensors and copying into ovrtx is acceptable.

  • Use Attribute Mapping when CUDA or CPU code should write directly into ovrtx-owned attribute buffers.

Notes#

  • Transform matrices are float64.

  • Semantics are write-side conversion hints. Attribute reads use the raw storage layout.

  • In C, a 4x4 matrix attribute is represented as shape=[N] with DLDataType{kDLFloat, 64, 16}.

  • In Python, a 4x4 matrix attribute is represented as shape=(N, 4, 4).