Last active
February 23, 2024 15:51
-
-
Save BigRoy/d1a4c7aa92d85db2c206f443fb521673 to your computer and use it in GitHub Desktop.
Houdini Solaris Material Library LOP get the USD Material Prim Path mapping to the Houdini Material node in the Material Library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
from typing import Dict | |
import hou | |
log = logging.getLogger(__name__) | |
def get_material_library_paths(material_lib: hou.LopNode) -> Dict[str, str]: | |
"""Return Houdini material node path to USD path mapping | |
Given a Houdini Material Library LOP provide a mapping of | |
all generated materials' USD paths to the relevant Houdini | |
material node paths. | |
Args: | |
material_lib (hou.LopNode): The Material Library LOP node. | |
Returns: | |
dict: Mapping from generated USD Material Prim Path to | |
the relevant Houdini Material VOP node path in the | |
Material Network. | |
""" | |
assert material_lib.type().name() == "materiallibrary" | |
material_lib.cook() # cook | |
modified_prims = set(material_lib.lastModifiedPrims()) | |
# Materials will be relative to this material network | |
material_network = material_lib.parm("matnet").evalAsNode() | |
if not material_network: | |
raise RuntimeError("No material network found") | |
material_path_prefix = material_lib.evalParm(f"matpathprefix") | |
mapping = {} | |
for i in range(material_lib.evalParm("materials")): | |
index = i + 1 | |
material_paths = material_lib.parm(f"matnode{index}").evalAsString() | |
if not material_paths: | |
continue | |
material_nodes = material_network.glob(material_paths) | |
if not material_nodes: | |
continue | |
material_flag_only = material_lib.evalParm(f"matflag{index}") | |
if material_flag_only: | |
material_nodes = [node for node in material_nodes | |
if node.isMaterialFlagSet()] | |
if not material_nodes: | |
continue | |
# Now for each material compute the resulting USD material path | |
matpath = material_lib.evalParm(f"matpath{index}") | |
for material_node in material_nodes: | |
if matpath: | |
node_matpath = matpath | |
else: | |
node_matpath = material_network.relativePathTo(material_node) | |
if not node_matpath.startswith("/"): | |
# Add material path prefix if path is not absolute already | |
node_matpath = f"{material_path_prefix}{node_matpath}" | |
mapping[node_matpath] = material_node.path() | |
# Let's do some re-assuring check to see if our computed output | |
# mappings correspond with the modified prims that Houdini lists | |
# for the LOP node. This is just a safety mechanism. | |
for path in mapping.keys(): | |
if path not in modified_prims: | |
log.warning( | |
"Expected generation of USD Material Path %s yet " | |
"it was not reported by Houdini as a modified " | |
"primitive by this LOP node '%s'", | |
path, material_lib.path() | |
) | |
return mapping | |
# Example usage | |
material_library = hou.node("/stage/materiallibrary1") | |
for usd_prim_path, houdini_node_path in get_material_library_paths(material_library).items(): | |
print(usd_prim_path, houdini_node_path) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
An easier method than the above is to just get the editor nodes from the modified prims of the Material Library. Those editor nodes will be the Material VOP nodes.
For example: