Authoring Geometry with USDRT and Rendering with FSD#

This document gives a brief example of authoring geometry directly to Fabric using the USDRT Scenegraph API, and rendering with Fabric Scene Delegate.

Create Geometry with USDRT Scenegraph API#

In the Kit Script Editor window, or your own extension code, authoring geometry is very similar to how it would be accomplished with the USD API. Here’s a small example that creates a triangle using a Mesh prim.

import omni.usd
from usdrt import Usd, Sdf, UsdGeom, Rt, Gf, Vt

stage_id = omni.usd.get_context().get_stage_id()

stage = Usd.Stage.Attach(stage_id)

prim = stage.DefinePrim("/World/Triangle", "Mesh")
mesh = UsdGeom.Mesh(prim)

points = mesh.CreatePointsAttr()
points.Set(Vt.Vec3fArray(
    [Gf.Vec3f(100.0, 0, 0), Gf.Vec3f(0, 100.0, 0), Gf.Vec3f(-100.0, 0, 0)]))
face_vc = mesh.CreateFaceVertexCountsAttr()
face_vc.Set(Vt.IntArray([3]))
face_vi = mesh.CreateFaceVertexIndicesAttr()
face_vi.Set(Vt.IntArray([0, 1, 2]))

rtbound = Rt.Boundable(prim)
world_ext = rtbound.CreateWorldExtentAttr()
world_ext.Set(Gf.Range3d(Gf.Vec3d(-100, 0, -100), Gf.Vec3d(100, 100, 100)))

rtxform = Rt.Xformable(prim)
local = rtxform.CreateFabricHierarchyLocalMatrixAttr()
world = rtxform.CreateFabricHierarchyWorldMatrixAttr()

After this code runs, the triangle should appear in your viewport:

A triangle in the Kit viewport

One potentially unfamiliar item in this example is the use of the Rt.Boundable and Rt.Xformable schema. Fabric Scene Delegate requires that all renderable prims hold attributes that contain the world and local transform matrices of the prim - the CreateFabricHierarchyLocalMatrixAttr() and CreateFabricHierarchyWorldMatrixAttr() APIs are the way to create and author that attribute.

Fabric Scene Delegate also prefers that all renderable prims hold an attribute that contains the extents of the prim in world space - the CreateWorldExtentAttr() API is the way to create and author that attribute. It is the responsibility of the author to calculate those extents and ensure their correctness.

Of course, Fabric Scene Delegate supports nearly all prim types in addition to Mesh. Let’s add a Cube to the scene:

prim = stage.DefinePrim("/World/Cube", "Cube")
cube = UsdGeom.Cube(prim)
size = cube.CreateSizeAttr()
size.Set(100)

rtbound = Rt.Boundable(prim)
world_ext = rtbound.CreateWorldExtentAttr()
world_ext.Set(Gf.Range3d(Gf.Vec3d(-50, -50, -50), Gf.Vec3d(50, 50, 50)))

xformable = Rt.Xformable(prim)
local = xformable.CreateFabricHierarchyLocalMatrixAttr()
world = xformable.CreateFabricHierarchyWorldMatrixAttr()

It should appear in the viewport intersecting the original triangle Mesh:

A cube and triangle in the Kit viewport

Fabric Scene Delegate also uses the same transform attributes as OmniHydra, as described in the Working with OmniHydra Transforms documentation. Let’s adjust the cube so that it sits below the triangle.

Note that the world extent matrix for the prim will need to be adjusted after the prim is transformed.

xformable = Rt.Xformable(prim)
local = xformable.GetFabricHierarchyLocalMatrixAttr()
local.Set(Gf.Matrix4d().SetTranslate(Gf.Vec3d(0, -50, -50)))

rtbound = Rt.Boundable(prim)
world_ext = rtbound.GetWorldExtentAttr()
world_ext.Set(Gf.Range3d(Gf.Vec3d(-50, -100, -100), Gf.Vec3d(50, 0, 0)))

Here is the result:

A cube below a triangle in the Kit viewport

It’s not my dream house, but it will have to do for now!