Houdini 18.5 Solaris

Primitive matching patterns

How to use the USD primitive matching syntax.

On this page


Many LOP nodes have a Primitives parameter that selects which USD primitives the node applies to. Often you will simply use the GUI to select the prims in the viewer or from a tree. This gives you a space-separated list of the selected paths, for example:

/house/chair1 /house/chair2 /house/table1

However, you can also craft strings that match path patterns, primitive attributes, combine matches using boolean operators, and more.

The pattern matching syntax for primitives is similar to other pattern matching languages in Houdini: a space-separated list of patterns, where the default is to combine the primitives "selected" by each pattern using "or" (union). The primitive pattern syntax also supports combining patterns using "and" (intersection) and "not".


Path patterns

In a path pattern, * matches any number of characters (in a name), ** matches any number of levels of hierarchy, ? matches any single character, and [...] matches any of the characters inside the square brackets.

Match the primitive with the path /Kitchen/Table/Leg1


Match all children of /Kitchen


Match any children of /Kitchen whose names start with Chair


Match any descendants of /Kitchen whose names are Handle1, Handle2, Handle3, or Handle4


Match any children of /House whose names are Room followed by a single character, such as RoomA



To match all primitives in a collection, specify the full path to the primitive holding the collection attribute, and the attribute name (with collection: prefix):

Match any prims specified by the KeyLights collection on the /House/LivingRoom primitive


As a shortcut, you can instead use %path_to_prim/collection_name:

Match any prims specified by the KeyLights collection on the /House/LivingRoom primitive


If your collection is on the /collections primitive, you can use an even shorter form %collection_name:

Match any prims specified by the KeyLights collection on the /collections primitive (This is the same as /collections.collection:KeyLights).


Auto Collections

Primitive patterns support a collection-like mechanism called auto collections. These are invoked using the collection syntax: %auto_type:auto_argument. Several auto collection types are supported natively by Solaris, and additional auto collection types can be added using the HDK. The traversal of the scene graph when using an auto collection is specific to each auto collection type to make it as fast as possible. So searching for a particular primitive kind can often skip over the traversal of most of the scene graph because of the rules of a USD model hierarchy:

Match all primitives of a particular USD kind using %kind:. To match all primitives of kind group, or any subkind of group (such as assembly)


Match all primitives with the supplied USD type using %type:. To match all light primitives that are derived from the base UsdLuxLight schema


Match all primitives with a particular purpose use %purpose:. To match all proxy or guide primitives


Match all primitives that reference, inherit from, or specialize the specified primitive using %reference:. To match all primitives that reference /prototype/tree


Match all primitives that share an instance master with the supplied primitive using %instance:. To match all primitives that are instances of the same master primitive as /instances/tree


Match all primitives that satisfy a selection rule using %rule:. To match all primitives specified by the /rules/Characters selection rule


Match all primitives that overlap a bounding box or camera frustum using %bound:. To match all primitives in the frustum of the camera at /cameras/camera1


Match all primitives targeted by a relationship using %rel:. The path to the relationship is provided as an argument. Relationships listed among the targets of the specified relationship will be expanded recursively. To match all target primitives of the products relationship on the primitive at /Render/rendersettings1


Match all primitives bound to a material using %geofrommat:. The path to a material primitive is provided as the first argument. A material purpose may also be specified, separated from the material path by a comma. To match all primitives with the material /materials/previewsurface1 assigned as a preview material


As a special case of finding all primitives bound to a material, to match all primitives with no bound material


Match all materials bound to any primitive on a branch of the scene graph tree using %matfromgeo:. The path to a primitive is provided as the first argument specifying the root of the scene graph branch to be inspected for bound materials. A material purpose may also be specified, separated from the material path by a comma. To match all materials bound to any primitives below /world/geo/house



You can enclose VEX code inside curly braces { } that evaluates to (or returns) 1 for "match" or 0 for "no match". In this snippet, @primpath matches the path of the current primitive being considered. You can also use @<attr_name> to access attribute values on the current primitive.

Match any primitives whose type is Mesh

{ usd_istype(0, @primpath, "Mesh") }

Match any primitives with a radius attribute whose value is greater than 20.

{ @radius > 2.0 }

(This is the same as { usd_attrib(0, @primpath, "radius") > 2.0 }.)

Match any primitives with a radius attributes whose value squared is greater than 4

{ float r2 = @radius * @radius; return r2 > 4; }

VEX has many useful usd_* functions for testing USD primitives. For example:

{ usd_purpose(0, @primpath) == "render" }

{ usd_variantselection(0, @primpath, "shapes") == "round" }

{ usd_istype(0, @primpath, "DiskLight") }

{ usd_iskind(0, @primpath, "component") }

{ usd_isinstance(0, @primpath) }

{ usd_isactive(0, @primpath) }

{ usd_isprim(0, @primpath) }

"Or" (union)

You can can combine two or more patterns, to match primitive that match any of the sub-patterns, using a + sign or just whitespace between the patterns:

Match primitive that are children of /house, or children of /yard, or children of /garage

/house/* + /yard/* + /garage/*

Same as above: whitespace between patterns is treated the same as the + operator.

/house/* /yard/* /garage/*

"And" (intersection)

You can combine two or more patterns to select only the primitives that match all of the sub-patterns, using the & operator:

Match any children of /Kitchen that are in the Props collection and also in the Static collection

/Kitchen/* & %Props & %Static 

"Not" (subtraction)

The - or ^ operator subtracts prims that match the pattern on the right side from any prims that match the pattern on the left side.

Match any children of /Kitchen that are not in the Lights collection

/Kitchen/* - %Lights

Match all children of /Kitchen whose names end in Chair except /Kitchen/HighChair

/Kitchen/*Chair ^ /Kitchen/HighChair


Use parentheses ( ) to group patterns together and treat them as a single pattern.

Match all children of /geo except /geo/foo and /geo/bar

/geo/* - (/geo/foo /geo/bar)

Ancestors and Descendants

Use the special tokens , , and to select all ancestor primitives, descendant primitives, or ancestor and descendant primitives of any primitives which match the patter up to that point. If these tokens appear inside a group, the ancestor and descendant expansion only applies to the primitives selected inside that group so far.

Match all components and their ancestors

{ usd_iskind(0, @primpath, "component") } <<

Match all descendants of components, but not the components themselves

{ usd_iskind(0, @primpath, "component") } >> - { usd_iskind(0, @primpath, "component") }

Match all the primitives matched by another primitive pattern parameter, but also include ancestors and descendants of those primitives

( `chs("../otherlop/primpattern")` ) <<>>

Improving Performance

Evaluating a primitive pattern can be quite expensive for very large scenes. In the worst case, every primitive on the entire stage must be compared to the pattern looking for matches. But there are also simple steps that can be taken to greatly improve the performance of a pattern.

  • Whenever possible, limit the scope of your search using And (&) operators. This operator can use information about one part of the pattern to limit the number of primitives that are evaluated against another part of the pattern. This is particularly important when using VEX Expressions, where providing a hint about what parts of the stage to traverse can reduce the number of primitives that get run through VEX. For example, /world/props/** & { usd_iskind(0, @primpath, "component") } will only run the VEX expression on primitives under /world/props.

  • Matching a primitive pattern that starts with * (such as *cam) will require a full traversal of the stage. Providing a prefix (such as /cameras/**cam) will confine the traversal to the /cameras branch, and may therefore be much faster. You can also use the And operator to limit the traversal (such as using /cameras/** & *cam).

  • The performance monitor pane’s node cook timing for LOP nodes explicitly separates out the time spent evaluating primitive patterns, which can help with finding expensive patterns.

Tips and tricks

  • The And (&) and Not (- or ^) operators bind to the closest single pattern on each side. Use parentheses if you want to group multiple patterns together on the left or right side.

    For example:

    /* - /a /b

    …means "/* or /b but not /a". If you want to express "/* but not /b or /c" you need to group the right side together:

    /* - (/a /b)

    (The underlying grammar is pretty simple. All operators except grouping parentheses have the same level, and all binary operators are left-associative. You will often need to use grouping to express exact meanings.)

  • The hou.LopSelectionRule object lets you evaluate the matching primitives given a stage and a primitive pattern string.




Karma renderer