Skip to content

Composition arcs

Syoyo Fujita edited this page Nov 8, 2024 · 13 revisions

W.I.P

Evaluation order

Composition op is resolved in the LIVRPS order(evaluate sublayer first)

  • Local(Sublayer)
  • Inherits
  • Variants
  • References
  • Payloads
  • Specializes

https://remedy-entertainment.github.io/USDBook/terminology/LIVRPS.html https://openusd.org/release/glossary.html#livrps-strength-ordering

Sublayers(LayerStack)

https://openusd.org/release/glossary.html#usdglossary-sublayers

Include(merge) external layers(USD files) into the root Stage.

Sublayer is evaluated in its appearance order. i.e, the first element in the 'subLayers' array is evaluated(included) firstly.

#usda 1.0
( subLayers = [ @000.usda@, @001.usda@, @002.usda@ ] )

# sublayer is evaluated in the following order: 000.usda, 001.usda, 002.usda.   

Sublayer's Stage(Layer) metadata is not loaded into the root Stage.

Can specify Layer Offsets in Sublayer.

PrimSpec's Specifier(def, over or class) is ignored

The layer itself as first and strongest. (e.g. The root layer is first and strongest against sublayer)

Pseudo code

def combine_prim(prim: PrimSpec, src: PrimSpec) -> [PrimSpec]:
   assert prim.name == src.name

   # if prim doesn't have typeName, set it from src's typeName
   if prim.typeName is empty:
      prim.typeName = src.typeName


   # append properties
   for src_prop in src.props:
      if not prim.props.has(src_prop):
         prim.props.append(src_prop)

   # recursively process combine_prim()
   for child_name in prim.children.names():
      if src.children.has(child_name):
         prim.children[child_name] = combine_prim(prim.children[child_name], src.children[child_name])

   # append src's child primspec
   for src_child in src.children:
      if not prim.children.has(src_child.name):
         prim.children.append(src_child)           
   
   return prim


def compose_subLayers(parent: Layer, sublayers: [str]) -> [PrimSpec]
   prims = parent.root_primspecs

   for sublayer_usd in sublayers:
      sublayer = load_usd(sublayer_usd)
      
      # process sublayer's subLayer first
      sublayer_prims = compose_subLayers(sublayer, sublayer.sublayers)

      for sublayer_prim in sublayer_prims:
         if prims.has(sublayer_prim.name):
            prims[sublayer_prim.name] = combine_prim(prims[sublayer_prim.name], sublayer_prim)
         else:
            prims.append(sublayer_prim)
      
   return prims


input = load_usd(input_usd)
root.primspecs = compose_subLayers(input, input.sublayers)
root.metadata = input.metadata

Inherits

Prims can "inherit" other Prims. Specifier(class, over or def) of 'base' Prims can be any.

Prims cannot inherit from an ancestor or descendant. (inherit Prim path must be a sibling of Prims or Prims in other Prims hierarchy)

def inherit_prim(prim: PrimSpec, base: PrimSpec) -> PrimSpec:

   prim = combine_prim(prim, base)

   return prim


root: Layer = ...

# recursively traverse PrimSpec tree
traverse primspec in root.primspecs:
   if primspec.has_inherits:
      assert primspec.inherits_primpath is not (ancestor or descendant of) primspec

      src = root.find_prim(primspec.inherits_primpath)
      primspec = inherit_prim(primspec, src)