• <xmp id="om0om">
  • <table id="om0om"><noscript id="om0om"></noscript></table>
  • USD (Universal Scene Description) is both an open source interchange format for arbitrary 3D scenes, as well as a runtime which provides a rich toolset for reading, writing, editing scenes.

    These tutorials will help Python developers new to USD learn how to perform common tasks on the scene graph, as well as learn how to be more proficient in the USD documentation.

    These tutorials are not meant to provide an introduction to 3D scene graphs and runtimes in general. Also, some experience with USD is beneficial but not required. If you have never encountered USD before, a good starting resource to get your hands dirty are the USD Tutorials from Pixar's USD site.

    The tutorials are organized by topic rather than sequential updates to a single goal, so they do not need to be read in any specific order.

    Opening USD Stages

    Working with USD Stages is pretty straight forward, as most times everything is one function call away.

    To load a USD file as a USD Stage you use Usd.Stage.Open(path):

    from pxr import Usd
    stage = Usd.Stage.Open('path_to_file.usd')

    To create a new Stage use Usd.Stage.CreateNew(path):

    from pxr import Usd
    stage = Usd.Stage.CreateNew('a_new_stage.usd')  

    To save a loaded Stage use Usd.Stage.Save(path)

    from pxr import Usd
    stage = Usd.Stage.Open('path_to_file.usd')
    # do something to the stage

    To export a stage to a new file, you can use Usd.Stage.Export(). This function allows you to transition between serialization formats (usda or usdc) as well, based on the file extension provided.

    from pxr import Usd
    stage = Usd.Stage.Open('a_usda_file.usda')
    # do something to the stage

    Prims, Attributes and Metadata


    Working with Prims is a more complicated since Prims are extremely powerful objects in USD. Prims are referenced by their path in the stage, which is a string in the form of /Prim/ChildPrim. / is a special prim known as the root prim in a stage.

    To get a reference to a prim at a path use stage_ref.GetPrimAtPath(path):

    from pxr import Usd
    stage_ref = Usd.Stage.Open('stage.usda')
    prim = stage_ref.GetPrimAtPath('/Prim')
    print(prim.GetName()) # prints "Prim"
    print(prim.GetPrimPath()) # prints "/Prim"

    To define a new prim use stage_ref.DefinePrim(path):

    from pxr import Usd
    stage_ref = Usd.Stage.Open('stage.usda')
    prim = stage_ref.DefinePrim('/UnTypedPrim')
    print(prim.GetName()) # prints "UnTypedPrim"

    To define a new prim with a type use stage_ref.DefinePrim(path, type_name) or you can use your Type's SomeType.Define(stage_ref, path) method:

    from pxr import Usd, UsdGeom
    stage_ref = Usd.Stage.Open('stage.usda')
    prim = stage_ref.DefinePrim('/XformPrim', 'Xform')
    # above we have a Usd.Prim, if we want to access all the Xform's types natively,
    we need to get an Xform instance of our prim
    xform = UsdGeom.Xform(prim)
    print(xform.GetPath()) # prints "/XformPrim"
    # it is often better to use the Define() method of your type right away, since
    it returns your typed instance rather than a Usd.Prim instance
    xform_faster = UsdGeom.Xform.Define(stage_ref, '/AnotherXformPrim')

    To delete a prim from the current edit layer (please refer to the documentation about RemovePrim for details) you can use stage_ref.RemovePrim(path):

    from pxr import Usd
    stage_ref = Usd.Stage.Open('stage.usda')
    prim = stage_ref.DefinePrim('/UnTypedPrim')
    if stage_ref.RemovePrim('/UnTypedPrim'):
    print('/UnTypedPrim removed')
    # if you try to access the prim object, it will still reference path but it is expired
    if (prim.IsValid()):
        print('{} is valid'.format(prim.GetName()))
        print('{} is not valid'.format(prim.GetName()))
    # the above will print "UnTypedPrim is not valid"


    Attributes are the workhorse of storing actual data inside a Prim. Attributes are often defined as part of Schemas to make it easier to access context-relevant data from within an instance of that Type.

    For example, Xform typed Prims have an attribute called Purpose which is used to specify the purpose of an imageable prim. It contains one of the following values: [default, render, proxy, guide]

    Now, you could get this attribute's value in two ways. One, as a generic prim_ref.GetAttribute(name) call, but you would have to know that the exact name of the attribute you want is "purpose", and you wouldn't be able to get any code completion in an IDE that way.

    The other way is to use the Xform Schema's exposed function for getting the purpose, which is xform_ref.GetPurposeAttr(), which returns the same object, but will be typed in an IDE and does not depend on the underlying string name of the attribute.

    Most often after you get an Attribute object, you will want to get the attribute's actual value or set it. That can be done with attribute_ref.Get() to retrieve the value, and attribute_ref.Set(value) to set the value.

    Note! attribute_ref.Set(value) requires passing the correct type of value as well, refer to table in Working with USD Types below to see how to construct the appropriate type.

    Let's see the code for getting an Attribute reference and getting its value:

    from pxr import Usd, UsdGeom
    stage_ref = Usd.Stage.Open('stage.usda')
    # get a reference to the Xform instance as well as a generic Prim instance
    xform_ref = UsdGeom.Xform.Define(stage_ref, '/XformPrim')
    prim_ref = xform_ref.GetPrim()
    # Get an attribute reference (not its value!)
    purpose_from_xform_ref = xform_ref.GetPurposeAttr()
    purpose_from_prim_ref = prim_ref.GetAttribute('purpose')
    print(purpose_from_xform_ref == purpose_from_prim_ref) # prints True
    # prints the actual attribute's value, in this case, one of [default, render,
    proxy, guide], since it is the Xform's actual Purpose attribute

    To create an attribute that isn't part of a Type's namespace (or it is, but you want to create the attribute "manually"), you must pass the attribute name and its type to prim_ref.CreateAttribute(name, type).

    Otherwise, most Types expose a Set -style command, for example xform_ref.SetPurposeAttr(value).

    The name of an Attribute is a string. The type system for Attributes (and USD in general) is explained below.

    Working with USD Types

    The USD API Documentation has a list of USD Basic Data Types that are used for Attribute types. Type Name are provided by the Sdf.ValueTypeNames module, which is a useful resource for reference.

    In order to actually pass a valid value for the type for the CreateAttribute(name, type) function, it needs to be a reference to a Sdf.ValueTypeNames.TypeName object. There are three ways of getting these:

      1. The current values and how to construct an object that will function as that value are in a table here for convenience, please refer to the USD Basic Data Types page for an explanation on explicit definitions. [] denotes a list of types. The left column of this list was generated with the method from 1) above.

      Note: Gf.Vec3d/f/h instances below can be constructed with just a (float, float, float) tuple (and Vec2d/f/h , Vec4d/f/h as well), but the explicit declaration is passed below for completeness.

      Attribute Type -> Constructor Table

      Type NamePython Constructor
      Color3dGf.Vec3d(float, float, float)
      Color3dArray[Gf.Vec3d(float, float, float)]
      Color3fGf.Vec3f(float, float, float)
      Color3fArray[Gf.Vec3f(float, float, float)]
      Color3hGf.Vec3h(float, float, float)
      Color3hArray[Gf.Vec3h(float, float, float)]
      Color4dGf.Vec4d(float, float, float, float)
      Color4dArray[Gf.Vec4d(float, float, float, float)]
      Color4fGf.Vec4f(float, float, float, float)
      Color4fArray[Gf.Vec4f(float, float, float, float)]
      Color4hGf.Vec4h(float, float, float, float)
      Color4hArray[Gf.Vec4h(float, float, float, float)]
      Double2(float, float)
      Double2Array[(float, float)]
      Double3(float, float, float)
      Double3Array[(float, float, float)]
      Double4(float, float, float, float)
      Double4Array[(float, float, float, float)]
      Float2(float, float)
      Float2Array[(float, float)]
      Float3(float, float, float)
      Float3Array[(float, float, float)]
      Float4(float, float, float, float)
      Float4Array[(float, float, float, float)]
      Frame4dfloat, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float
      Frame4dArray[Gf.Matrix4d(float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float)]
      Half2(float, float)
      Half2Array[(float, float)]
      Half3(float, float, float)
      Half3Array[(float, float, float)]
      Half4(float, float, float, float)
      Half4Array[(float, float, float, float)]
      Int2(int, int)
      Int2Array[(int, int)]
      Int3(int, int, int)
      Int3Array[(int, int, int)]
      Int4(int, int, int, int)
      Int4Array[(int, int, int, int)]
      Int64long or int in Python3
      Int64Array[long] or [int] in Python3
      Matrix2dfloat, float, float, float
      Matrix2dArray[Gf.Matrix2d(float, float, float, float)]
      Matrix3dfloat, float, float, float, float, float, float, float, float
      Matrix3dArray[Gf.Matrix3d(float, float, float, float, float, float, float, float, float)]
      Matrix4dfloat, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float
      Matrix4dArray[Gf.Matrix4d(float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float)]
      Normal3dGf.Vec3d(float, float, float)
      Normal3dArray[Gf.Vec3d(float, float, float)]
      Normal3fGf.Vec3f(float, float, float)
      Normal3fArray[Gf.Vec3f(float, float, float)]
      Normal3hGf.Vec3h(float, float, float)
      Normal3hArray[Gf.Vec3h(float, float, float)]
      Point3dGf.Vec3d(float, float, float)
      Point3dArray[Gf.Vec3d(float, float, float)]
      Point3fGf.Vec3f(float, float, float)
      Point3fArray[Gf.Vec3f(float, float, float)]
      Point3hGf.Vec3h(float, float, float)
      Point3hArray[Gf.Vec3h(float, float, float)]
      QuatdGf.Quatd(float, Gf.Vec3d(float, float, float))
      QuatdArray[Gf.Quatd(float, Gf.Vec3d(float, float, float))]
      QuatfGf.Quatf(float, Gf.Vec3f(float, float, float))
      QuatfArray[Gf.Quatf(float, Gf.Vec3f(float, float, float))]
      QuathGf.Quath(float, Gf.Vec3h(float, float, float))
      QuathArray[Gf.Quath(float, Gf.Vec3h(float, float, float))]
      TexCoord2dGf.Vec2d(float, float)
      TexCoord2dArray[Gf.Vec2d(float, float)]
      TexCoord2fGf.Vec2f(float, float)
      TexCoord2fArray[Gf.Vec2f(float, float)]
      TexCoord2hGf.Vec2h(float, float)
      TexCoord2hArray[Gf.Vec2h(float, float)]
      TexCoord3dGf.Vec3d(float, float, float)
      TexCoord3dArray[Gf.Vec3d(float, float, float)]
      TexCoord3fGf.Vec3f(float, float, float)
      TexCoord3fArray[Gf.Vec3f(float, float, float)]
      TexCoord3hGf.Vec3h(float, float, float)
      TexCoord3hArray[Gf.Vec3h(float, float, float)]
      UCharord(char) where char is a single letter string
      UInt64long or int in Python3
      Vector3d Gf.Gf.Vec3d(float, float, float)
      Vector3dArray[Gf.Vec3d(float, float, float)]
      Vector3fGf.Vec3f(float, float, float)
      Vector3fArray[Gf.Vec3f(float, float, float)]
      Vector3hGf.Vec3h(float, float, float)
      Vector3hArray[Gf.Vec3h(float, float, float)]

    2. Use Sdf.ValueTypeNames.Find(string) to get the reference from a string (valid inputs are the left column in the table above)

    3.Look up the exact value for TypeName in the Sdf.ValueTypeNames module ( Sdf.ValueTypeNames.Color3h for example is valid):

    from pxr import Sdf
    # output is: ['Asset', 'AssetArray', 'Bool', 'BoolArray', 'Color3d',
    'Color3dArray', 'Color3f', 'Color3fArray', 'Color3h', 'Color3hArray', 'Color4d',
    'Color4dArray', 'Color4f', ... snipped ]

    Coming back to Working with Attributes

    You can call the prim_ref.CreateAttribute(name, type) function to create the attribute, and we can use the information above to select a valid type. It returns a reference to the attribute created, which we can set with attribute_ref.Set(value) , and again we can construct a valid value by looking up the constructor above.

    from pxr import Usd, UsdGeom
    stage_ref = Usd.Stage.Open('stage.usda')
    # get a reference to the Xform instance, this works fine since it is also a Usd.Prim
    xform_ref = UsdGeom.Xform.Define(stage, '/XformPrim')
    # create an attribute reference, using an explicit reference to the type
    weight_attr = xform_ref.CreateAttribute('weight', Sdf.ValueTypeNames.Float)
    print(weight_attr.Get()) # prints empty string for default Float values, not 0!
    print(weight_attr.Get() == None) # prints "True"
    print(weight_attr.Get() == 0) # prints "False"
    # to set an attribute we use the attribute_ref.Set(value) function
    print(weight_attr.Get()) # prints "42.3"
    # also, you can chain calls like so
    print(xform_ref.GetPrim().GetAttribute('weight').Get()) # prints "42.3"

    Hierarchy and Traversal

    USD Stages are organized in a hierarchy of Prims: there is a special root prim at / and it may have N-number of direct Prim descendants, each of which can have their own tree of Prim descendants.

    The path to a Prim is described by a string which starts with the root prim / and contains the Prim name separated by the path separator / until the last component is the desired Prim's name.

    For example /Car/Wheel/Tire refers to the Tire prim which has parent Wheel and grandparent Car. Car's parent is the special root prim /.

    In the Tutorial section on Stages there is information on how to retrieve a Prim at a given path using stage_ref.GetPrimAtPath().

    Here is a refresher, we'll assume car.usda has the /Car/Wheel/Tire path:

    from pxr import Usd
    stage_ref = Usd.Stage.Open('car.usda')
    prim_ref = stage_ref.GetPrimAtPath('/Car')

    Now, if you want to get a specific child of a Prim, and you know the name, you can use prim_ref.GetChild(child_name):

    from pxr import Usd
    stage_ref = Usd.Stage.Open('car.usda')
    prim_ref = stage_ref.GetPrimAtPath('/Car')
    child_prim_ref = prim_ref.GetChild('Wheel')
    # Prims can be cast as bool, so you can check if the prim exists by comparing
    its bool() overload
    if child_prim_ref:
        print("/Car/Wheel exists") # this will execute
    print(child_prim_ref.GetPath()) # prints ""/Car/Wheel"

    If you want to get all the children of a Prim, you can use prim_ref.GetChildren() which returns a list of prim references:

    from pxr import Usd
    stage_ref = Usd.Stage.Open('car.usda')
    prim_ref = stage_ref.GetPrimAtPath('/Car')
    # will return [Usd.Prim(</Car/Wheel>)]
    children_refs = prim_ref.GetChildren()

    If you want to traverse the entire stage, the stage_ref.Traverse() function is perfect for that, it returns an iterator:

    from pxr import Usd
    stage_ref = Usd.Stage.Open('car.usda')
    for prim_ref in stage_ref.Traverse():

    There are more advanced traversal methods described in the UsdStage documentation.