from random import randint
import hou
from hou import hmath
from pxr import UsdGeom, Usd, Gf, Vt
node = hou.pwd()
stage = node.editableStage()
colName = node.evalParm("collectionName")
colPath = node.evalParm("collectionPath")
protoPath = node.evalParm("protoPath")
instName = node.evalParm("instancerName")
primpathpoints = node.evalParm("pointsprimpath")
prim_path_for_points = primpathpoints
points_prim = stage.GetPrimAtPath(prim_path_for_points)
if not points_prim:
raise RuntimeError(f"Prim not found at {prim_path_for_points}")
points_geom = UsdGeom.Points(points_prim)
if not points_geom:
raise RuntimeError(f"Prim at {prim_path_for_points} is not a Points prim")
positions_attr = points_geom.GetPointsAttr()
positions = positions_attr.Get()
if not positions:
raise RuntimeError(f"No points found at {prim_path_for_points}")
numinstances = len(positions)
orientations = []
scales = []
all_attrs = points_prim.GetAttributes()
for attr in all_attrs:
name = attr.GetName()
if not name.startswith("primvars:"):
continue
value = attr.Get()
if value is None or len(value) != numinstances:
print(f"Skipping {name}: empty or mismatched size")
continue
if name == "primvars:orient":
first = value[0]
if isinstance(first, Gf.Vec4f):
orientations = [
Gf.Quath(v[3], Gf.Vec3h(v[0], v[1], v[2]))
for v in value
]
elif isinstance(first, Gf.Quatf):
orientations = [
Gf.Quath(q.GetReal(), Gf.Vec3h(*q.GetImaginary()))
for q in value
]
elif isinstance(first, Gf.Quath):
orientations = list(value)
else:
print(f"Unsupported orient type: {type(first)}")
elif name == "primvars:scale":
first = value[0]
if isinstance(first, Gf.Vec3f):
scales = list(value)
else:
print(f"Unsupported scale type: {type(first)}")
if not orientations:
print("Warning: 'primvars:orient' not found or failed, using default identity quaternions.")
orientations = [Gf.Quath(1, Gf.Vec3h(0, 0, 0)) for _ in range(numinstances)]
if not scales:
print("Warning: 'primvars:scale' not found or failed, using default Vec3f(1,1,1).")
scales = [Gf.Vec3f(1.0, 1.0, 1.0) for _ in range(numinstances)]
proto_scope = UsdGeom.Scope.Define(stage, protoPath)
UsdGeom.Imageable(proto_scope).MakeInvisible()
collection_owner_path = colPath
collection_name = colName
collection_owner = stage.GetPrimAtPath(collection_owner_path)
collection_api = Usd.CollectionAPI.GetCollection(collection_owner, collection_name)
targets = collection_api.GetIncludesRel().GetTargets()
instancer_prim = stage.DefinePrim(instName, "PointInstancer")
pi = UsdGeom.PointInstancer(instancer_prim)
source_points_rel = instancer_prim.CreateRelationship("sourcePoints")
source_points_rel.SetTargets([points_prim.GetPath()])
rel = pi.GetPrototypesRel()
for target in targets:
rel.AddTarget(target)
protoindices = pi.GetProtoIndicesAttr()
protoindices.Set(Vt.IntArray([randint(0, len(targets) - 1) for _ in range(numinstances)]))
pi.GetPositionsAttr().Set(Vt.Vec3fArray(positions))
pi.GetOrientationsAttr().Set(Vt.QuathArray(orientations))
pi.GetScalesAttr().Set(Vt.Vec3fArray(scales))
for attr in points_prim.GetAttributes():
name = attr.GetName()
if not name.startswith("primvars:"):
continue
value = attr.Get()
if value is None:
continue
inst_attr = instancer_prim.CreateAttribute(name, attr.GetTypeName(), custom=True, variability=attr.GetVariability())
if isinstance(value, (list, tuple, Vt.Vec3fArray, Vt.QuathArray, Vt.IntArray)):
inst_attr.Set(value)
else:
inst_attr.Set(value)