Houdini 19.0 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, or using a more expression function syntax: %auto_type(auto_argument1, auto_argument2, ...). The function syntax supports both optional named arguments and ordered arguments specified without a name. Most auto collections only accept one or two required arguments, and so do not support the named syntax. Refer to the documentation for each auto collection for details about its required and optional arguments.

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:

%abstract/solaris/(<>)

Match all primitives that are abstract (or are not abstract, if the optional bool argument is specified as 0, no, or false). An abstract primitive is one which has a specifier of class, or where any ancestor primitive is abstract. All other primitives without any class primitives in their hierarchy are not abstract.

To match all abstract primitives

%abstract
%abstract(true)
%ancestors(primpattern, strict=bool)

Match all ancestors of another primitive or group of primitives. Accepts a single required argument which is a primitive pattern. The optional strict argument can be set to 0, no, or false to return the members of the source pattern as well as their ancestors.

To find all ancestors of all component primitives

%ancestors(%kind:component)
%bound:primpath

Match all primitives that overlap a bounding box or camera frustum, or which overlap an arbitrary bounding box. Because of these different capabilities, several different signatures are supported.

To match all primitives in the frustum of the camera at /cameras/camera1

%bound:/cameras/camera1
%bound(/cameras/camera1)

To match all primitives which overlap the bounding box of the prim at /world/geo1

%bound:/world/geo1
%bound(/world/geo1)

To enlarge the bounds of the camera frustum by virtually moving the camera backwards, use the optional dolly argument

%bound(/cameras/camera1, dolly = 50)

To match all primitives which overlap the bounding box defined by a particular minimum and maximum point in world space

%bound(min = [-1, -1, -1], max = [1, 1, 1])

To match all primitives which overlap the bounding box defined by a center point and box dimensions (equivalent to the bounds defined above)

%bound(center = [0, 0, 0], size = [2, 2, 2])
%children(primpattern, strict=bool)

Match all children of another primitive or group of primitives. Accepts a single required argument which is a primitive pattern. The optional strict argument can be set to 0, no, or false to return the members of the source pattern as well as their children.

To find all direct children of /World, and return /World itself

%children(/World, strict=false)
%closerthan(primpath, distance)

Match all primitives with a bounding box that is less than a certain distance from a primitive.

To match all primitives within 10 units of /cameras/camera1

%closerthan:/cameras/camera1,10
%closerthan(/cameras/camera1, 10)
%commonroots(primpattern)

Match the most deeply nested primitive that contains all primitives in the supplied pattern. If the pattern contains primitives under multiple root primitives, the primitives under each root are processed separately. So this auto collection will return one primitive for each root primitive branch in the specified pattern. This auto collection can be useful to determine where in the scene graph hierarchy to author a collection material binding, which must be on a primitive that contains all the primitives to be bound to the material.

To find the most nested primitive under which all components in a scene appear

%commonroots(%kind:component)
%defined/solaris/(<>)

Match all primitives that are defined (or are not defined, if the optional bool argument is specified as 0, no, or false). A defined primitive is one which has a specifier of def or class, and where all ancestor primitives are defined. Any primitive which has a specifier of over, or has an ancestor with a specifier of over is not defined.

To match all primitives that are not defined

%defined:false
%defined(false)
%descendants(primpattern, strict=bool)

Match all descendants of another primitive or group of primitives. Accepts a single required argument which is a primitive pattern. The optional strict argument can be set to 0, no, or false to return the members of the source pattern as well as their descendants.

To find all descendants of all Material primitives, and the Material primitives themselves

%descendants(%type:Material, strict=false)
%fartherthan(primpath, distance)

Match all primitives with a bounding box that is more than a certain distance from a primitive.

To match all primitives more than 10 units from /cameras/camera1

%fartherthan:/cameras/camera1,10
%fartherthan(/cameras/camera1, 10)
%geofrommat(primpattern, bindingpurpose)

Match all primitives bound to a material. The path to a material primitive is provided as the first argument. A material purpose may also be specified.

To match all primitives with the material /materials/previewsurface1 assigned as a preview material

%geofrommat:/materials/previewsurface1,preview
(geofrommat:/materials/previewsurface1, preview)

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

%geofrommat:none
%highest(primpattern)

Match the set of primitives that match the enclosed pattern, and which have no ancestors which match the pattern. This rule is similar to the minimalset auto collection, and is useful to minimize the number of opinions that need to be authored to generate an equivalent result. It is different than that auto collection in that it will only ever return prims that directly match the enclosed pattern.

To find the least nested group primitives in a scene

%highest(%kind:group)
%instance/solaris/(<>)

Match all primitives that share an instance prototype with the supplied primitive. If no primitive is specified, all primitives with any instance prototype will match the pattern.

To match all primitives that are instances of the same master primitive as /instances/tree

%instance:/instances/tree
%instance(/instances/tree)
%instanceproxy/solaris/(<>)

Match all primitives that are instance proxies (or are not instance proxies, if the optional bool argument is specified as 0, no, or false).

To match all primitives that are not instance proxies

%instanceproxy:false
%instance(false)
%keep(primpatern, start=int, end=int, count=int, interval=int, keepoutsiderange=bool)

Keeps a subset of primitives that match the supplied primpattern. The matching primitives are considered to be in an alphabetically sorted list based on each primitive’s path. In the range from start to end, count of every interval primitives are kept. For primitives before start or after end, the primitives are kept if keepoutsiderange is true, otherwise primitives outside the range are removed.

The default values for these arguments are 0 for start and end is the number of primitives. The default for count is 1 and interval is 2. This means by default every other primitive is kept. The default for keepoutsiderange is false. Negative values can be used for start, end, count, and interval. If so, the value is set to the number of primitives matching the primpattern minus the magnitude of the value.

To match two thirds of all children of /world/props/rocks/*

%keep(/world/props/rocks/*, count=2, interval=3)
%keeprandom(primpatern, seed=float, fraction=float)

Keeps a subset of primitives that match the supplied primpattern. The matching primitives are placed into a random order determined by each primitive’s path and the seed value. Once placed in this random (but stable) sorting order, primitives are removed until only the specified fraction remains. fraction should be between 0.0 and 1.0. The defaults value is 0.5. The seed value defaults to 0.0, and each different value will result in a different sorting order of the primitives.

To match one quarter of all components, with a random seed of 0.6

%keeprandom(%kind:component, fraction=0.25, seed=`0.6`)
%kind(kind1, kind2, …, strict=bool)

Match primitives based on their USD kind. Accepts one or more names of USD kinds. The optional strict argument can be used to control whether this auto collection matches subkinds or not. By default, subkinds are allowed.

To match all primitives of kind group, or any subkind of group (such as assembly)

%kind:group
%kind(group)

To match all primitives of kind group, but not any subkinds of group

%kind(group, strict=true)
%lowest(primpattern)

Match the set of primitives that match the enclosed pattern, and where all direct children of this prim don’t also match the pattern. This rule is roughly the opposite of the highest auto collection, but in order to ensure consistent results for inheritable attributes, it may leave both a parent and child prim in the set if the parent needs to be there to cover siblings of the child that are not in the set.

To find the most nested group primitives in a scene

%lowest(%kind:group)
%matfromgeo(primpattern, bindingpurpose)

Match all materials bound to any primitive on a branch of the scene graph tree. 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 binding purpose may also be specified.

To match all materials bound to any primitives below /world/geo/house

%matfromgeo:/world/geo/house
%minimalset(primpattern)

Match the minimal set of primitives on which an inheritable value would need to be set in order for the value to be set on all the primitives listed in the supplied pattern. Inheritable properties include activation, visibility, and constant primvars. This rule is useful to minimize the number of opinions that need to be authored to generate an equivalent result.

To find the minimal set of prims that would need to be marked invisible in order for all components except /world/geo/house to be invisible

%minimalset(%kind:component - /world/geo/house)
%parents(primpattern, strict=bool)

Match all direct parents of another primitive or group of primitives. Accepts a single required argument which is a primitive pattern. The optional strict argument can be set to 0, no, or false to return the members of the source pattern as well as their parents.

To find all parents of component primitives

%parents(%kind:component)
%purpose:purpose1,purpose2,…

Match all primitives with one of a set of purposes. Multiple purposes can be provided.

To match all proxy or guide primitives

%purpose:proxy,guide
%purpose(proxy, guide)
%reference:primpattern

Match all primitives that reference, inherit from, or specialize any primitives in the specified pattern.

To match all primitives that reference /prototype/tree

%reference:/prototype/tree
%reference(/prototype/tree)
%referencedby:primpattern

Match all primitives that appear in a reference, inherit, or specialize composition arc on any primitive in the specified pattern.

To match all primitives that are referenced by /props/*

%referencedby:(/props/*)
%rel:relpath

Match all primitives targeted by a relationship. 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

%rel:/render/rendersettings1.products
%rel(/render/rendersettings1.products)
%rel(primpattern, relname)

Match all primitives targeted by a relationship on multiple primitives. The primitive pattern is expanded, and the named relationship is queried from each primitive. Relationships listed among the targets of the specified relationship will be expanded recursively.

To match all render vars on any render product of /Render/rendersettings1

%rel(%rel(/render/rendersettings1, products), orderedVars)
%rendercamera:primpath

Match the camera targeted by the default RenderSettings prim. A different RenderSettings prim can also be provided as an optional argument.

To match all target primitives of the products relationship on the primitive at /Render/rendersettings1

%rendercamera
%rendercamera:/Render/settings
%renderproducts:primpath

Match all RenderProducts a targeted by the default RenderSettings prim. A different RenderSettings prim can also be provided as an optional argument.

To match all target primitives of the RenderProducts prims on the default render settings prim for the current stage

%renderproducts

To match all target primitives of the RenderProducts prims on the primitive at /Render/rendersettings1

%renderproducts:/Render/settings1
%renderproducts(/Render/settings1)
%rendersettings

Match the default render settings on the the stage.

To match the default render settings on the current stage

%rendersettings
%rendervars:primpath

Match all RenderVars a targeted by RenderProducts on the default RenderSettings prim. A different RenderSettings prim can also be provided as an optional argument.

To match all target primitives of the RenderVars prims on the default render settings prim for the current stage

%rendervars

To match all target primitives of the RenderVars prims on the primitive at /Render/rendersettings1

%rendervars:/Render/settings1
%rendervars(/Render/settings1)
%rule:selection_rule

Match all primitives that satisfy a selection rule.

To match all primitives specified by the /rules/Characters selection rule

%rule:/rules/Characters
%rule(/rules/Characters)
%shadertype(idpattern1, idpattern2, …)

Match all UsdShade primitives with a SourceId that matches one of the provided patterns. The patterns are standard Houdini string matching patterns, allowing wildcards and exclusions. The comparisons are case-insensitive.

To find all USD primvar reader shader nodes (regardless of the data type they read)

%shadertype(UsdPrimvarReader_*)
%specifier:specfier/solaris/,<>

Match all primitives configured with one of the listed specifiers. Valid specifiers are def, over, and class. See the glossary for more information about the meanings of these terms. Note that unlike the abstract and defined auto collections, the specifiers of ancestor primitives will not affect the results of this auto collection. A primitive with a specified of def may not be defined, and this auto collection can find such cases.

To match all defined primitives

%specifier:def
%specifier(def)
%type(primtype1, primtype2, …, strict=bool)

Match all primitives of a particular USD type. Accepts one or more names of USD primitive types. The optional strict argument can be used to control whether this auto collection matches derived types or not. By default, derived types are allowed.

To match all light primitives that are derived from the base UsdLuxLight schema

%type:UsdLuxLight
%type(UsdLuxLight)
%variant(setname1=value1 value2, setname2=value3 value4, …)

Match all primitives with a particular variant set selection. The setname part of each argument is the variant set name. Each setname argument must be unique. But for each set name, the list of values can use standard Houdini string matching semantics, including the use of wildcards. All comparisons of variant set names and selections are case sensitive.

To match all primtives with a modelingVariant of ChairB

%variant(modelingVariant=ChairB)
%visible/solaris/(<>)

Match all primitives that are visible (or are invisible, if the optional bool argument is specified as 0, no, or false). In either case, only UsdGeomImageable primitives will be matched by this pattern, though imageable primitives under untyped or non-imageable primitives will also be returned, so this pattern is not quite equivalent to asking which primitives will (or will not) appear in the viewport.

To match all primitives that are not visible

%visible:false
%visible(false)

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 pattern 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")` ) <<>>

These special tokens are equivalent to the ancestors and descendants auto collections with strict mode set to false.

Auto collection equivalent to >>

%descendants(pattern, strict=false)

Auto collection equivalent to <<

%ancestors(pattern, strict=false)

Auto collection equivalent to <<>>

%ancestors(%descendants(pattern), strict=false)

Pruning

Many common operations in LOPs involve targeting primitives that appear above a certain point in the hierarchy. For example, it is often useful to find all primitives matching a particular condition, but only if they exist outside of an asset definition (indicated by the component kind on the primitive). As an example, consider an attempt to find all Xform primitives that are outside of any component.

One way to accomplish this is by finding all Xform primitives, then remove the ones that are inside components.

Match all Xform primitives

%type:Xform

Match all Xform primitives, then remove any that are inside components

%type:Xform - (%kind:component >>)
%type:Xform - %descendants(%kind:component, strict=false)

Note that this is not quite equivalent to finding all Xform primitives that are also ancestors of component primitives, because there may be Xforms in branches with no components. All of the patterns above involve a traversal of the whole stage. A more efficient approach would be to simply stop the traversal (prune the scene graph tree) when a component is found. This can be expressed using the Prune operator ~.

A much more efficient way to find Xforms outside of components

%type:Xform ~ %kind:component

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.

  • The most efficient search is one that doesn’t happen. Try to use Pruning (~) to prevent traversals.

  • 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

Geometry

  • Importing SOP geometry into USD

    Details of how Houdini converts SOP geometry to USD, and how you can control the process.

  • Component Builder

    The Component Builder tool puts down a network snippet for creating a USD model from SOPs, with support for materials, variants, payloads, and layering.

Layout

  • Edit node

    Interactively transforms prims in the viewer. Can use physics collisions to position props realistically.

  • Layout node

    Provides tools for populating a scene with instanced USD assets. You can place individual components, paint/scatter components in different ways using customizable brushes, and edit existing instances.

  • Custom Layout Brushes

    How to create layout brush digital assets you can use to customize the behavior of the Layout LOP.

Shading

  • Shader Framework

    Describes the Solaris shading framework, including shader node translation to USD primitives.

  • Using MaterialX with Karma

    Houdini has VOP node equivalents of the MaterialX shader nodes. You can build a shader network using these nodes, or import an existing MaterialX shader, and use them with Karma (Houdini’s USD renderer).

  • /solaris/materialx_nodes

Karma rendering

Tutorials