Akshay Parkhi's Weblog

Subscribe

Learning OpenUSD — From Curious Questions to Real Understanding

19th March 2026

Written as I explored OpenUSD before my exam. These are real questions I asked, and the answers that actually made things click for me.

1. Overview — What is OpenUSD?

OpenUSD (Universal Scene Description) is an open-source framework developed by Pixar for describing, composing, and simulating 3D scenes. It is now the industry standard for film, VFX, games, robotics, and simulation.

Think of it like a file format + scene graph + composition engine all in one. It lets multiple departments (modelling, animation, lighting, FX) work on the same scene simultaneously without stepping on each other.

2. Stage — The Container of Everything

The Stage is the entry point to any USD scene. It is the root container that holds all objects (prims), layers, and time settings.

from pxr import Usd

stage = Usd.Stage.CreateNew("scene.usda")
stage.Save()

Think of the Stage like a theatre stage — a space where everything exists. Without a stage, there is nowhere to put your actors (prims).

Key things the stage controls:

  • Which layers are loaded
  • Time settings (start frame, end frame, fps)
  • The entire prim hierarchy

3. Prims — Objects in the Stage

Prims (short for Primitives) are the objects that live on the stage. Everything you see in a USD scene is a prim — a sphere, a cube, a camera, a light, even an empty group.

from pxr import Usd, UsdGeom

sphere = UsdGeom.Sphere.Define(stage, "/World/MySphere")
cube   = UsdGeom.Cube.Define(stage,   "/World/MyCube")

Prims are organised in a hierarchy — exactly like folders on your computer:

/World                     ← parent prim (like a folder)
├── /World/Room            ← child prim
│   ├── /World/Room/Chair  ← grandchild prim
│   └── /World/Room/Table  ← grandchild prim
└── /World/MySphere        ← another child

If you move /World, everything inside moves with it.

4. Properties — The Data Inside a Prim

Properties are the actual data stored inside a prim. If a prim is like a file, properties are the content of that file.

sphere.GetRadiusAttr().Set(1.0)
sphere.GetDisplayColorAttr().Set([(1,0,0)])  # red color

There are two types of properties:

TypeWhatExample
AttributeA value on the primradius, color, translate
RelationshipA pointer to another primmaterial binding → /Materials/Red

Properties answer the question: “What IS this object?” (its shape, color, position, size)

5. TimeCode — The Frame Number

A TimeCode is a unitless number representing a point in time — like a frame number. It has no inherent unit until the stage gives it meaning.

stage.SetStartTimeCode(1)
stage.SetEndTimeCode(60)
stage.SetMetadata("timeCodesPerSecond", 24)  # 24 frames = 1 second

With timeCodesPerSecond = 24, timeCode 48 = 2 seconds of real time.

Think of timeCode as the X-axis on a graph — it is just a position on the timeline, not a value itself.

6. TimeSamples — Animation Keyframes

TimeSamples are values pinned to specific timeCodes on an attribute. This is how you animate things in USD.

sphere.AddTranslateOp().Set(Gf.Vec3d(0, 5, 0), time=1)   # frame 1  → Y=5 (top)
sphere.AddTranslateOp().Set(Gf.Vec3d(0, 0, 0), time=30)  # frame 30 → Y=0 (bottom)
sphere.AddTranslateOp().Set(Gf.Vec3d(0, 5, 0), time=60)  # frame 60 → Y=5 (top)

USD linearly interpolates between timeSamples automatically:

Frame:  1    15   30   45   60
Y pos:  5    2.5  0    2.5  5
        ▲         ▲         ▲
     keyframe  keyframe  keyframe
       (yours)  (yours)   (yours)

You author 3 keyframes — USD fills in all 60 frames. That is the bounce you see in usdview.

TimeSeries vs TimeSamples:

  • TimeSeries = the full animation from start to end (all 60 frames)
  • TimeSamples = the keyframes you author (just 3 snapshots)

You can put a timeSample on every frame if needed (e.g. physics simulation, motion capture) but for simple animation, fewer keyframes is better — smaller file size and USD handles the smooth interpolation.

7. Prim and Property Paths

Every prim and property in USD has a path — a unique address to find it, just like a file path on your computer.

/World/Room/Chair          ← prim path  (address of the object)
/World/Room/Chair.size     ← property path (address of the data inside)
from pxr import Sdf

# Get a prim by its path
chair = stage.GetPrimAtPath("/World/Room/Chair")

# Build paths programmatically
base  = Sdf.Path("/World/Room")
path  = base.AppendChild("Chair")         # /World/Room/Chair
prop  = path.AppendProperty("size")       # /World/Room/Chair.size

# Check if a prim exists
chair.IsValid()   # True
sofa = stage.GetPrimAtPath("/World/Room/Sofa")
sofa.IsValid()    # False — doesn't exist

Path = where to find it. Properties = the actual data stored inside.

8. OpenUSD File Format

USD scenes are saved as text files you can open and read directly.

#usda 1.0

def Sphere "BouncingSphere"
{
    double radius = 1.0
    color3f[] displayColor = [(1, 0, 0)]

    double3 xformOp:translate.timeSamples = {
        1:  (0, 5, 0),
        30: (0, 0, 0),
        60: (0, 5, 0),
    }
}

Common file formats:

FormatTypeUse
.usdaText (ASCII)Human readable, good for learning
.usdcBinary (crate)Compact, fast, used in production
.usdzZip archivePackages all assets together (AR, iOS)

USD also supports plugins for other formats like .abc (Alembic) and .fbx.

9. OpenUSD Modules

USD is organised into modules — like Python packages. You import only what you need.

from pxr import Usd, UsdGeom, Sdf, Gf, UsdShade, UsdPhysics
ModuleFull NameWhat it does
UsdUniversal Scene DescriptionStage, prims, properties — the main engine
SdfScene Description FoundationLayers, file format, paths
GfGraphics FoundationMath — Vec3d, Matrix4d, colors
UsdGeomUSD GeometrySphere, Cube, Mesh, Xform
UsdShadeUSD ShadingMaterials and shaders
UsdPhysicsUSD PhysicsPhysics simulation

pxr is the top-level package (installed on your machine). All modules live inside it.

Custom schemas — you can also define your own prim types by extending:

  • UsdTyped — when your prim IS a thing (e.g. RobotArm, SO101Joint)
  • UsdAPISchemaBase — when your schema ADDS behaviour to any prim (like a mixin)
  • usdGenSchema — the tool that generates boilerplate code for your custom schema

10. Metadata — Info About the Object

Metadata is extra information attached to a stage, prim, or property. It is not geometry data — it describes context around the object.

# Stage metadata
stage.SetMetadata("timeCodesPerSecond", 24)

# Prim metadata — who made it, version, notes
sphere.GetPrim().SetMetadata("assetInfo", {
    "author": "gajanan",
    "version": "1.0",
    "approved": True
})

# Property metadata — document what an attribute does
sphere.GetRadiusAttr().SetMetadata("documentation", "radius of the sphere in cm")

Metadata vs Attributes:

MetadataAttribute
AnswersWhat do we KNOW about it?What IS it?
Example"author: gajanan"radius = 1.0
Animatable?NoYes (timeSamples)
LikeEXIF data on a photoThe actual pixels

Standard metadata keys:

  • assetInfo — asset name, version, author
  • customData — your own project-specific notes
  • documentation — describe what a property does

In a real studio pipeline with hundreds of assets, metadata is how you track, annotate, and manage everything without touching the geometry.

Quick Reference Cheatsheet

from pxr import Usd, UsdGeom, Sdf, Gf

# Stage
stage = Usd.Stage.CreateNew("scene.usda")
stage.SetStartTimeCode(1)
stage.SetEndTimeCode(60)
stage.SetMetadata("timeCodesPerSecond", 24)

# Prims
sphere = UsdGeom.Sphere.Define(stage, "/World/Sphere")

# Properties
sphere.GetRadiusAttr().Set(1.0)

# TimeSamples (animation)
sphere.AddTranslateOp().Set(Gf.Vec3d(0, 5, 0), time=1)
sphere.AddTranslateOp().Set(Gf.Vec3d(0, 0, 0), time=30)

# Paths
prim = stage.GetPrimAtPath("/World/Sphere")
path = Sdf.Path("/World").AppendChild("Sphere")

# Metadata
prim.SetMetadata("customData", {"author": "gajanan"})

stage.Save()

This is Learning OpenUSD — From Curious Questions to Real Understanding by Akshay Parkhi, posted on 19th March 2026.

Next: OpenUSD Mastery: From Composition to Pipeline — A SO-101 Arm Journey

Previous: 7 Mental Models for Building Agent Skills (From Anthropic's Internal Playbook)