Python lop taking multiple inputs/stages

   2144   3   2
User Avatar
Member
14 posts
Joined: 3月 2019
Offline
Is it possible to have python LOP taking stages from other LOPs? I am doing something similar to the graft LOP by using python LOP. Basically using Sdf.CopySpec with custom filter functions to copy prims from one layer to another.
A side question, so does graft LOP using Sdf.CopySpec under the hood?
User Avatar
スタッフ
4438 posts
Joined: 7月 2005
Offline
The python LOP can access any other LOP node's stage using hou.node(“/stage/lopnode”).stage() or hou.node(“/stage/lopnode”).activeLayer(). However be aware that given an arbitrary LOP network, there is no guarantee that the USD stage returned by stage() calls will be valid after you call stage() on the next LOP node. So I'd highly recommend grabbing each input LOP node's stage, and copying the information you need to use to a temporary layer or stage. In particular make sure not to call editableStage() or editableLayer() to modify the Python LOPs data until all stages from other LOP nodes have been released.

The Graft LOP does use SdfCopySpec (but flattens the layer stack first, otherwise CopySpec would only be able to copy the data from a single layer, not the fully composed prim).
User Avatar
Member
14 posts
Joined: 3月 2019
Offline
Thank you Mark!
Yes, I tried calling stage() from other node in a python LOP before, and it didn't work for me. I will try copying the information to a temp in-memory stage next time. thanks for the tip!
I have another Graft LOP question(or bug?). I notice that the Graft LOP will update the prefix of the paths of a relationship property, which make sense in most cases, but it also prefixes paths that have no internal parent prims (e.g. class prims.) I am not sure if that is intentional.

This is how pixar's copySpec handles the case.
https://github.com/PixarAnimationStudios/USD/blob/release/pxr/usd/sdf/copyUtils.cpp#L680 [github.com]

I also attached a hip file to show the situation.

Attachments:
graft.hip (48.4 KB)

User Avatar
スタッフ
451 posts
Joined: 6月 2020
Offline
Hi Wayne,

Thanks for that example .hip; I can clearly see what you've described. I made some changes to your test scene to (hopefully) help illustrate a few things.

The good news (or bad news - depending on how you look at it) is that the behaviour is intentional.

The Graft LOP (now “Graft Stages” in Houdini 18.5) emulates an SdfCopySpec call on the (pseudo-)root prim, with the assumption that the source stage is fully self-contained and relocatable. We can't directly SdfCopySpec the ‘/’ prim, so we instead call it sequentially on all the root prim's children, and make a small change to the way we call it (I'll come back to this shortly).

In your example, you're calling SdfCopySpec on /geom which inherits from /_prototype etc. The inheritance path isn't updated because it (/_prototype) isn't a child of the thing that you're copying (/geom). There are two things I'd consider here:

1 - If you add /_prototype to the stage you're grafting, it's going to end up being relocated to /parent/transform/_prototype and now the inheritance path (if it doesn't update) will be pointing at the wrong spot. You can see this in the change I made to inlineusd1 (to add /_prototype) and copySpec (to more closely - but not perfectly - emulate what Graft Stages does). That's probably not what you want.

2 - If you changed the scene structure such that you had /copyMe/geom which inherited from /copyMe/_prototype and you called SdfCopySpec on /copyMe then the inheritance path *would* get updated. You can see this in the inlineusd2 change. I'm not suggesting you want to do this, but rather just trying to make it more explicit when paths do/don't get updated. Again, because we're trying to emulate copying the root prim in Graft Stages, when we use SdfCopySpec, we tell it to update all references under ‘/’ (as opposed to only updating references under the prim being copied). It's not obvious, but the code difference is here:
https://github.com/PixarAnimationStudios/USD/blob/release/pxr/usd/sdf/copyUtils.cpp#L827 [github.com]
vs
https://github.com/sideeffects/HoudiniUsdBridge/blob/master/src/houdini/lib/H_USD/HUSD/XUSD_Utils.C#L1942 [github.com]

The workflow in your example scene (which I appreciate may not match your production target) may be more amenable to Graft Branches (introduced in Houdini 18.5), which lets you cherry-pick specific prims to copy, and then only updates paths that contain said prim as a prefix (i.e., you can graft /geom and the LOP will only update paths that start with /geom, leaving ‘/’ paths as-is). Worded differently, this allows you to have relationship targets outside the prim you're grafting and those paths will be left intact. I'd say that your existing Python LOP more closely matches what Graft Branches does than what Graft Stages does.

I hope this helps! Please let me know if there's anything you feel is still unclear or unexpected or we should reconsider.
Edited by robp_sidefx - 2020年10月20日 08:27:19

Attachments:
graft_sidefx.hip (53.0 KB)

  • Quick Links