houdini 匯入 FBX 大量節點合併與材質整理

最近常處理max或maya的FBX丟進來的場景,通常匯進來的FBX要在另外建一個sop做合併彙整,但必須是一個node對一個object merge來針對各自物件做不同碎裂,如果FBX裏面物件很多,合併起來是相當麻煩的事情,所以這種重複的作業還是寫一個script去處理比較適當。

hou.ui.setStatusMessage("Select source node", severity=hou.severityType.Message)
source = hou.ui.selectNode()
if source != None and source != "":
    hou.ui.setStatusMessage("Select target node", severity=hou.severityType.Message)
    target = hou.ui.selectNode()
if source == None or source == "" or target == None or target == "":
    hou.ui.displayMessage("Invalid nodes", ("OK",), hou.severityType.Warning, title="Warning")
else:   
    s_node = hou.node(source)
    t_node = hou.node(target)

    import_list = []
    create_list = []

    for child in s_node.children():
        if child.type().name() == "geo":
            import_list.append(child.name())
    for node in import_list:
        m = t_node.createNode("object_merge")
        create_list.append(m)
        m.parm("objpath1").set(source + "/" + node)
        m.parm("xformtype").set(1)

    chk_merge = hou.ui.displayMessage("Merge all node?", ("Yes", "No"), hou.severityType.Message, title="Warning")
    if chk_merge == 0:
        merge = t_node.createNode("merge")
        for node in create_list:
            merge.setNextInput(node)

    t_node.layoutChildren() 

另外,FBX匯進來的物件,其物件材質會有兩種情況:如果是單一材質,材質會上在SOP上,如果是多重(multi-ID)材質,他會在SOP裡新增group跟material節點。假如一個FBX包含以上兩種,之後把整個FBX的物件合併,會發現前者的材質沒辦法帶到,因為該物件primitive的shop_materialpath屬性沒有東西,所以必須要針對該物件去寫上屬性,這種事情也是很常發現,故也寫了一個script。

hou.ui.setStatusMessage("Select FBX subnetwork", severity=hou.severityType.Message)
selectNode = hou.ui.selectNode()
if selectNode == None or selectNode == "":
    hou.ui.displayMessage("Invalid node", ("OK",), hou.severityType.Warning, title="Warning")

else:
    chk_clean = hou.ui.displayMessage("Clean material path?", ("Yes", "No"), hou.severityType.Message, title="Warning")
    for node in selectNode.children():

        if node.type().name() == "geo":
            mpath = node.parm("shop_materialpath")

            if mpath.eval() != "":

                mat = node.path().replace(node.name(), mpath.eval()[3:])

                geo_node = None
                for child in node.children():
                    if child.isRenderFlagSet():
                        geo_node = child
                        break

                mat_node = node.createNode("material")
                mat_node.parm("shop_materialpath1").set(mat)
                mat_node.setNextInput(geo_node)
                mat_node.setRenderFlag(True)
                mat_node.setDisplayFlag(True)
                if chk_clean == 0:
                    mpath.set("")