Jump to content
Sign in to follow this  
Atom

Selection To Object Merge

Recommended Posts

This has come up quite often for me when working with imported static FBX files. Often you will get every little piece of a model inside it's own geo object but you really just want to work with them all as a single mesh.

This script will examine your node selection and create a new /obj level object that will object merge in all the nodes selected into a single merge. Then you can just use that single node to represent your model. (i.e fix up normals, detail materials, prepare for simulation, export etc...)

 

import hou

THRESHOLD = 0.015
def luminance(pixel):
    return (0.299 * pixel[0] + 0.587 * pixel[1] + 0.114 * pixel[2])

def is_similar(pixel_a, pixel_b, threshold):
    return abs(luminance(pixel_a) - luminance(pixel_b)) < threshold

lst_user_selection = hou.selectedNodes()
if len(lst_user_selection):
    
    # Make a geo node that will ObjectMerge in all the nodes in the selection.
    node_geo = hou.node('/obj').createNode("geo","geo_merge_result")
    if node_geo:
        node_geo.moveToGoodPosition()
        #node_geo.node('file1').destroy()
        node_merge = node_geo.createNode('merge')
        node_merge.moveToGoodPosition()

        # Create a normal to fix up everything after the merge.
        node_normal = node_geo.createNode("normal","normal1")
        node_normal.setInput(0, node_merge)                # Create a NULL for our output placeholder.
        node_normal.setDisplayFlag(True)
        node_normal.setRenderFlag(True)
        node_normal.moveToGoodPosition()
        
        # Create a NULL for our output placeholder.
        node_null = node_geo.createNode("null","OUT")
        node_null.setInput(0, node_normal)                # Create a NULL for our output placeholder.
        node_null.setDisplayFlag(True)
        node_null.setRenderFlag(True)
        node_null.moveToGoodPosition()
                
        for (n,node) in enumerate(lst_user_selection):
            print node.name()
            node_temp = node_geo.createNode("object_merge",node.name())
            node_temp.parm('objpath1').set(node.path())
            node_temp.parm('xformtype').set(1)
            node_temp.moveToGoodPosition()
            
            assign_by_node_color = True
            if assign_by_node_color:
                # Use the color of nodes to inherit the same @shop_materialpath.
                s = "rs_DEFAULT"
                if is_similar(node.color().rgb(), (0.584,0.776,1.0), THRESHOLD): s = "rs_blue3"
                if is_similar(node.color().rgb(), (0.6,0.6,0.6), THRESHOLD): s = "rs_grey5"
                if is_similar(node.color().rgb(), (0.145,0.667,0.557), THRESHOLD): s = "rs_green5"
                if is_similar(node.color().rgb(), (1.0,0.725,0.0), THRESHOLD): s = "rs_yellow6"
                if is_similar(node.color().rgb(), (0.996,0.933,0.0), THRESHOLD): s = "rs_yellow5"
                
                # Create a wrangle to define our shop_materialpath.
                node_wrangle  = node_geo.createNode("attribwrangle","attribwrangle1")
                node_wrangle.parm('snippet').set('s@shop_materialpath = "/shop/%s";' % s)
                node_wrangle.parm('class').set(1)
                node_wrangle.moveToGoodPosition()
                node_wrangle.setInput(0, node_temp)

                # Create a color to match the node color.
                node_color  = node_geo.createNode("color","color1")
                node_color.parm('colorr').set(node.color().rgb()[0])
                node_color.parm('colorg').set(node.color().rgb()[1])
                node_color.parm('colorb').set(node.color().rgb()[2])
                node_color.moveToGoodPosition()
                node_color.setInput(0, node_wrangle)
                
                node_merge.setInput(n,node_color)
            else:
                node_merge.setInput(n,node_temp)

 

In this image the white areas were not part of the selection. The color of the nodes in the selection is forwarded into the object merge as an additional color node. There is also an attribute wrangle added inline to assign the @shop_materialpath based upon the color detected. This can convert objects with same exact material referencing multiple copies of the same material into a single /shop path material. You can adjust to /mat if needed.

Untitled-1.jpg

Edited by Atom
  • Like 3
  • Thanks 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×