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
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
%rel:/render/rendersettings1.products
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
%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
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
%matfromgeo:/world/geo/house
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.