Houdini 18.5 Solaris

Primitive matching patterns

How to use the USD primitive matching syntax.

On this page

Overview

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".

Syntax

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

/Kitchen/Table/Leg1

Match all children of /Kitchen

/Kitchen/*

Match any children of /Kitchen whose names start with Chair

/Kitchen/Chair*

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

/Kitchen/**/Handle[1234]

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

/House/Room?

Collections

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

/House/LivingRoom.collection:KeyLights

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

%/House/LivingRoom/KeyLights

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).

%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)

%kind:group

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

%type:UsdLuxLight

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

%purpose:proxy,guide

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

%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

%instance:/instances/tree

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

%rule:/rules/Characters

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

%bound:/cameras/camera1

Vexpressions

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

Grouping

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.

Solaris

USD

Tutorials

Karma renderer