Jump to content

Selection To Object Merge


Atom

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 5
  • Thanks 3
Link to comment
Share on other sites

  • 1 year later...

You the man!! Thank you sooo much for this! Just used it for and it helped sooo much!

For any newbies out there like me confused at how to use this:

You use the script by pasting the code into a new shelf tool (in the script panel) that you create by right_clicking in an empty area on any shelf.

Then on /obj level - I went inside the fbx import node and selected all the nodes the import had created, ctr+cliked the the new tool in the shelf and I had a new organized node waiting for me on /obj level.

Thank you so much once again for sharing this with the community, Atom! 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...