moving the privot of packed primitives

Today I had to move all pivots of an packed primitive object for an rbd simulation. If the centroid, center of mass or origin doesn’t fit your needs, maybe this could be interesting.

// move the pivot of all packed primitives

vector oMoveIntrinsicPivot = chv("MoveIntrinsicPivot");
@P += oMoveIntrinsicPivot;
setprimintrinsic(0, "pivot",@primnum,oMoveIntrinsicPivot,"add");       

Creating bgeo files from selected objects

After importing FBX files, hip files are getting very large. To avoid saving all geometry for every scene it makes sense to save the data to disk. For 3-4 objects it’s no big deal to do this by hand, but when dealing with hundreds of objects, this is getting annoying. Here is a small snipped, that reads the current houdini selection and exports files to $HIP/geo/`opname(“..”)`/`opname(“..”)` This is really the basic approach without any versioning, it gives you a good starting point how to set this up.

import hou  
oSelection = hou.selectedItems()

if oSelection == 0:
    print "nothing is selected"
    for oSelectedNode in oSelection:
        c = oSelectedNode.children()
        for n in c:
            p = n.path()
            node = hou.node(p)
            type = hou.nodeFlag.Render
            flag = node.isGenericFlagSet(type)
            if flag == 1:
                oFlaggedNode = n
                #print (p + " Render Flag is " + str(flag))
        oNewROPNode = oSelectedNode.createNode("rop_geometry")
        oNewROPNode.setInput(0, oFlaggedNode )
        oNewFileNode = oSelectedNode.createNode("file")
        c = oSelectedNode.children()
        for n in c:
            p = n.path()
            node = hou.node(p)
            type = hou.nodeFlag.Render
            flag = node.isGenericFlagSet(type)
            if flag == 0:

Select objects with this material

Like the “Assign Material to Selection” function, all Softimage/Maya Guys know the “Select objects with his martial” button. I know this is already an option under the material palette. But who uses this? So here is the code to get the same functionality in Houdini. Just copy/paste the code into this file: C:\Users\USER\Documents\houdini17.0\OPmenu.xml And you are done. On the next houdini restart it should pop up on the right mouse button menu.


<?xml version="1.0" encoding="UTF-8"?>
        <scriptItem id="TM_Util_SelectObjectsWithThisMaterial">
            <label>TM Tools: Select Objects with this Material</label>
import hou
oselectedNodes = hou.selectedNodes()
oShaderTypes = ["redshift::Material", "principledshader::2.0", "redshift_vopnet", "material" ]

for mats in oselectedNodes:
    oShaderCheck = 0
    oShaderType = str(mats.type().name())
    for item in oShaderTypes:
        if oShaderType in item:
                oShaderCheck = 1
    if oShaderCheck == 1:
        oNodes = mats.dependents()
        for oNode in oNodes:
            if str(oNode.type().name()) == "geo":
                #print oNode.path()



Assign Material to Selection

All Maya and Softimage Guys know the option “Assign to Selection”. Here is the Houdini equivalent ;). Just copy/paste this code into the this file: C:\Users\USER\Documents\houdini17.0\OPmenu.xml

Node: if there is no file yet, just create one. Houdini should pick it up on the next startup. And as you see, currently it works exclusively for redshift materials and the standard principed shader. If you want to use other shader types add them to the oShaderTypes variable.

<?xml version="1.0" encoding="UTF-8"?>
        <scriptItem id="Util_AssignMaterialToSelection">
            <label>Tools: Assign Material to Selection</label>
import hou
shader = kwargs.get("node", None)
oselectedNodes = hou.selectedNodes()
oShaderCheck = 0
oShaderTypes = ["redshift::Material", "principledshader::2.0", "redshift_vopnet", "material" ]
oShaderType = str(shader.type().name())

for item in oShaderTypes:
    if oShaderType in item:
        oShaderCheck = 1

if oShaderCheck == 1:
    for oNode in oselectedNodes:
        if str(oNode.type().name()) == "geo":
        	#print "assign" + str(shader.path()) + " to " + str(oNode.path())


Retiming Stuff (the old way)

Hey, last week I had the case that I had to do some liquid retiming within Houdini 16.5. Meaning, that there is no proper retime SOP as in Houdini 17. So I did it the classical way with findattrib. If you are in Houdini 16.x this is definitively a way to check out. I have attached an image of my tree. It works really nice, also with changing pointcounts. The only thing that I had to care about was to save an id attribute within my flip simulation. 

Merge Objects into new Geometry

Hey! long time no post. But, now it’s time to post some stuff again. The first small script I want to share is a script, that has been handy during the last productions. It merges a geo object selection to an new geo and adds it’s material as primitive material. Maybe you were asking, why we sometimes are working like this. Houdini doesn’t display instanced subnets in the viewport and redshift doesn’t render instanced subnets. This is a workaround to fully instance subnet/objects in the viewport and at rendertime. Sure this is just a workflow for small assets, but for smaller products that need to be instanced this can be a solution. Also If you have to do some multi object editing. :).

import hou

#Get Houdini Selection
oSelection = hou.selectedItems()
#Create an empty List
oAllObjsforSubnet = []
#Create an empty Counter
counter = 0

#Check if the selection is empty
if oSelection:
    #The the obj context to the variable obj
    obj = hou.node("/obj")
    #create a new Geo Node on /obj level
    newNode = obj.createNode("geo", str("merged_geo"))
    #Delete the build in File node of the new Geo
    #Create the hero merge node
    oMergeNode = newNode.createNode("merge")
    #Loop over the selected node
    for oNode in oSelection:
        #Check if the type is geo
        if oNode.type().name() == "geo":
            #Create an Obeject Merge node
            currentOBJMerge = newNode.createNode("object_merge")
            #Set the path to the base obj
            #Check if there is an Material assigned
            if(oNode.evalParm("shop_materialpath") != ""):
                #Create a SOP materail node
                currentMaterial = newNode.createNode("material")
                #Convert relative Pathes to absolute pathes
                relPath = oNode.evalParm("shop_materialpath")
                relNode = oNode.node(relPath)
                fullpath = relNode.path()
                #Fill in the right materail path
                #Connect the current obj merge node the the materail node
                #Connect the material node the the hero merge node
            #If there is no Material assigned
                #Connect the Object Merge to the 
            #Increase the ounter, for the next merge node port
            counter +=1
    #Set the diplay Flag


Instance/copy objects with nulls

Hey there,

when dealing with real commercial productions it is, at some point, necessary to place object instances by hand. There for you have four options in Softimage.

  1. A hard copy of the object
  2. A clone of the object
  3. Put it in a Model and use an model instance
  4. Use ICE to distribute instances in combination with Nulls that have an PPG with an integer attribute to detect the instance.

Point four is the workflow I like the most, because it is super flexible. After the placement it is possible to change all attributes e.g. with a random size or position. Now the question is, how do I adapt my known workflow to Houdini? Exact the same way I do it in SI. Fist we need to create a null object with an integer attribute “instNR” for instance number, some instances and a geometry that holds the geometry.

Lets dive into geometry level. First I have tried to build a setup the classical way. With maaaany attribute create sops. 

“Going from top to bottom you see that I create all attributes I need to transfer the data from the null objects: i@instNR, f@pscale, v@scale, v@euler_rot, 4f@orient. In the point vop I convert the euler rotation to a quaternion rotation. This is needed because the copy sop is using quaternions. With the path attribute of the object_merge sop we can access all attributes like this: ch(@objname + “/../instNR”). The only attribute we have to samp is the Instance Number. The syntax in the copy sop is like this: point(“../Input_GEO_OUT1”, $PT, “pinstNR”, 0). The switch node can now access this attribute like this: stamp(“../copy_InstancesToPoints”, “pinstNR”, 0). This is all we need to get it working.

Much slicker is to do all attribute manipulation in an attribute wrangle.

That’s all. Easy to setup and effective. The only thing to notice here is, that this is a copy NOT a instance workflow. To really instance objects I recommend this tutorial. this workflows here can easily combined with this workflow. Here InstanceObjectsWithNulls you can download the example hip file.

SOP: Transform Pieces

This is probably now one of my all time favourite nodes in Houdini: “Tansform Pieces”! For the next project I’m doing some research on how to move poly islands effectively. I started doing my own stuff, but than I came across the Transform Pieces node, that does the whole job for me! Great!