On this page |
Overview ¶
As part of making SOP nodes compilable, we separated out the node’s basic operation code (what the node does to geometry) from the code that deals with the concerns of the node (caching, reading inputs, evaluating parameters, and so on). We call these functions verbs. You can use them in Python scripting to modify geometry held in a hou.Geometry object. This might be useful anywhere you need to programmatically alter geometry and don’t want to have to build a geometry network to do so.
Getting a verb ¶
-
hou.NodeTypeCategory.nodeVerb returns the verb for the named node type:
box_verb = hou.sopNodeTypeCategory().nodeVerb("box")
-
If you have a reference to a specific SOP node already, you can use hou.SopNode.verb to get the corresponding verb:
node = hou.node("/obj/geo1/box") box_verb = node.verb()
-
hou.NodeTypeCategory.nodeVerbs returns a dictionary mapping node type names to verbs:
verbs = hou.sopNodeTypeCategory().nodeVerbs() box_verb = verbs["box"] sphere_verb = verbs["sphere"]
You can list the available SOP “verbs” in a Python shell with:
sorted(hou.sopNodeTypeCategory().nodeVerbs().keys())
Using a verb ¶
Using a verb is a two-step process: set the parameters on the verb, then apply the verb to a hou.Geometry object.
-
Set the parameters on the verb.
Pass a dictionary to hou.SopVerb.setParms where the keys are the internal names of the parameters. You can see the internal name of a parameter in the Parameter Editor by hovering over the parameter’s name.
box_verb.setParms({ "t": hou.Vector3(0.5, -0.5, 2.0), "scale": 0.5, })
Multiparms are set by passing in a list/tuple of dictionaries for the multiparm parameter name. The dictionaries should have the token names with # rather than digits in them. Note in this example the tuple needs the trailing comma to count as a tuple - a single dictionary will not work.
add_verb.setParms({ 'points': [ { 'usept#': True, 'pt#': (1, 2, 3), } ] })
Note
References operators must use absolute paths. Usually when verbs execute it is outside any particular node, so there is no relative path to refer to.
-
Apply the verb to a geometry object.
Before you do this you must have a geometry object. You can create an empty Geometry object:
geo = hou.Geometry()
Then you can execute the verb and write its output to the geometry object:
box_verb.execute(geo, [])
If your verb has inputs (for example, the /nodes/sop/copy.html verb takes the geometry to copy and the points to copy onto), you can supply hou.Geometry objects representing the inputs in the second argument. You can get a live read-only reference to of the geometry from a node using hou.SopNode.geometry.
c2p_verb = hou.sopNodeTypeCategory().nodeVerb("copytopoints") instance = hou.node("/obj/geo1/sphere1").geometry() points = hou.node("/obj/geo1/pointcloud").geometry() c2p_verb.execute(geo, [instance, points])
Note
When you execute()
a verb, it overwrites the geometry you pass it. If you want to combine multiple generators (or multiple generator/filter chains), you must generate each piece in a “buffer” Geometry
object, and merge the pieces into a “main” Geometry
using hou.Geometry.merge.
sops = hou.sopNodeTypeCategory() box = sops.nodeVerb("box") box.setParms({"scale": 0.25}) geo = hou.Geometry() temp = hou.Geometry() for x in (-0.5, 0.5): for y in (-0.5, 0.5): for z in (-0.5, 0.5): box.setParms({ "t": hou.Vector3(x, y, z) }) box.execute(temp, []) geo.merge(temp)
Notes and tips ¶
-
You can use a Python SOP to preview, test, or debug your geometry generation script. It outputs a hou.Geometry object you build in the node’s Python code parameter.
-
hou.SopVerb.execute always overwrites the Geometry object you supply. If you want to add to an existing Geometry object, execute into an empty Geometry, then use hou.Geometry.merge to merge it with another Geometry object.
# Existing content we want to add to existing_geometry = hou.node("/obj/geo1/phone").geometry() # Blank geometry to hold new content new_geometry = hou.Geometry() # Write into the new geometry box_verb.execute(new_geometry, []) # Add the new geometry into the existing geometry existing_geometry.merge(new_geometry)
-
If you are using verbs to modify geometry inside a Python SOP, you need to overwrite the node’s geometry at the end of the script:
# Grab a reference to this node node = hou.pwd() geo = node.geometry() # ... operate on geometry ... # When verbs execute on the hou.Geometry they may replace the # underlying geometry rather than in-place edit it. So you have # to explicitly write it back to the node's geometry. node.geometry().clear() node.geometry().merge(resultgeo)
Example ¶
The following example grabs the geometry from a node and applies the Subdivide and IsoOffset verbs to it.
node = hou.node("/obj/geo1/testgeometry_pighead1") geo = node.geometry() resultgeo = hou.Geometry() # Get a hou.SopVerb that knows how to subdivide. sops = hou.sopNodeTypeCategory() subverb = sops.nodeVerb('subdivide') # Pass in a dictionary mapping parameter names to values. # Node defaults are already set, so just set non-default things. subverb.setParms({'iterations': 3}) # SopVerb.execute() takes a target hou.Geometry to write the results into, # and a list of hou.Geometry to be the inputs of the verb (use None in the # list to represent an unwired input). subverb.execute(resultgeo, [geo]) # Now do an isooffset isoverb = sops.nodeVerb('isooffset') isoverb.setParms({'samplediv':100, 'output':0}) isoverb.execute(resultgeo, [resultgeo])