Houdini 11 Houdini Object Model HOM Cookbook

Overview

This example illustrates how to retrieve and set transformations on object nodes.

Location

Supporting files for this example are in $HFS/houdini/help/hom/cookbook/object_xform, also found in the cookbook/object_xform directory of cookbook_files.tar.gz.

Getting Started

Load obj_xform.hip and you’ll see a series of boxes chained together in a transformation hierarchy. Translate and rotate a box object in the middle of the chain to see that the outputs of that box inherit the transformations.

Open up a Python shell window in Houdini and observe the effects on box_object4 in both the viewport and network editor as you enter the following:

# Store the hou.ObjNode for /obj/box_object4 into a Python variable.
>>> box_object4 = hou.node("/obj/box_object4")
>>> box_object4
<hou.ObjNode of type geo at /obj/box_object4>

# Ask for box_object4's world transformation.  This transformation matrix
# includes the parm transformation (determined from the translate, rotate,
# scale, etc. parameters on the object), pretransformations, parent
# transformations, transformations on the containing object, etc.
>>> xform = box_object4.worldTransform()
>>> xform
<hou.Matrix4 [[0.942106, -0.147233, -0.301261, 0],
[0.134676, 0.988938, -0.062158, 0],
[0.3070 8, 0.017987, 0.951514, 0],
[-5.04816, -0.769449, -9.42593, 1]]>

# Disconnect box_object4's input.  box_object4 will move, since it no longer
# inherits its input's transformations.  If we print out its new transformation
# matrix, we see that it's different.
>>> box_object4.inputs()
(<hou.ObjNode of type geo at /obj/box_object3>,)
>>> box_object4.setFirstInput(None)
>>> box_object4.inputs()
()
>>> box_object4.worldTranform()
<hou.Matrix4 [[0.966956, 0, 0.254942, 0],
[0, 1, 0, 0],
[-0.254942, 0, 0.966956, 0],
[0.885497 , 0, -3.01977, 1]]>

# Restore box_object4's transformation to its previous value.  We'll leave
# its input disconnected, so we'll have unparented it but kept its position.
# setWorldTransform will adjust the objects parameters to achieve the
# desired end result, accounting for inputs, pretransforms, etc.
>>> box_object4.setWorldTransform(xform)

Writing a Function to Unparent

Next, let’s package up the logic to unparent a node and keep its position into a function, and we’ll call that function on box_object4 from a shelf tool.

Reload obj_xform.hip so that box_object4 is parented again, and add the following code to a new shelf tool. Right-click on an empty area of the shelf, select New Tool, create a tool named “Unparent”, and add the following in the Script tab:

def unparentAndKeepPos(obj_node):
    """Unparent an object node, but keep it in the same position as it was
       when it was parented.
    """
    xform = obj_node.worldTransform()
    obj_node.setFirstInput(None)
    obj_node.setWorldTransform(xform)

unparentAndKeepPos(hou.node("/obj/box_object4"))

Unparenting the Selected Node

Let’s generalize the shelf tool to work with the viewport’s selected node instead of box_object4. To do that, we can use hou.SceneViewer.selectObjects to return the currently selected object. Here is the new shelf tool:

# The toolutils module ships with Houdini and is used to perform common
# shelf tool operations.  It can be found in $HFS/houdini/python2.5libs.
import toolutils

def unparentAndKeepPos(obj_node):
    """Unparent an object node, but keep it in the same position as it was
       when it was parented.
    """
    xform = obj_node.worldTransform()
    obj_node.setFirstInput(None)
    obj_node.setWorldTransform(xform)

# If an object is already selected, we'll use it.  If nothing is selected,
# we'll prompt the user to select something.  If multiple objects are selected,
# we'll use the last one, since that should correspond to the parameter pane
# contents.
viewer = toolutils.sceneViewer()
obj_node = viewer.selectObjects(quick_select=True)[-1]
unparentAndKeepPos(obj_node)

Reparenting the Selected Node

Next, let’s write another shelf tool that will reparent the selected node. It will prompt the user for the new parent node.

# The toolutils module ships with Houdini and is used to perform common
# shelf tool operations.  It can be found in $HFS/houdini/python2.5libs.
import toolutils

def parentAndKeepPos(obj_node, new_parent):
    """Parent an object node, but keep it in the same position as it was
       when it was unparented.
    """
    xform = obj_node.worldTransform()
    obj_node.setFirstInput(new_parent)
    obj_node.setWorldTransform(xform)

# We'll select the object to reparent in the same way the unparent tool works.
# We'll prompt the user to select the new parent in the viewer.
viewer = toolutils.sceneViewer()
node_to_reparent = viewer.selectObjects(quick_select=True)[-1]
new_parent = viewer.selectObjects(use_existing_selection=False,
    quick_select=True,
    prompt="Select new parent node")[-1]
parentAndKeepPos(node_to_reparent, new_parent)
See also