Mark Tucker
mtucker
About Me
EXPERTISE
Developer
Connect
LOCATION
Canada
WEBSITE
Houdini Skills
Availability
Not Specified
My Badges
SideFX Staff
Since Jul 2005
Houdini Academy Advisor
Since Jan 2024
Recent Forum Posts
.stage() / .editableStage() usage Dec. 19, 2024, 3:14 p.m.
No, you can only use one or the other.
If you're careful, and know that what you're doing is "safe" (you'll have to do your own research to make such a determination), you can accomplish something very similar. Call editableStage, but then create an Sdf.ChangeBlock, and use Sdf APIs on the "edit target layer" rather than using Usd APIs on the Usd.Stage. Using this approach you could create all your prims inside an Sdf.ChangeBlock, end the change block, then use the Usd APIs to author your collection.
Also, there is nothing in USD that can _only_ be done with USD APIs. Because all Usd APIs boil down to calling Sdf APIs in the C++ code. It just may require some investigation and experimentation to figure out what Sdf APIs you need to call to accomplish what the Usd APIs are doing.
If you're careful, and know that what you're doing is "safe" (you'll have to do your own research to make such a determination), you can accomplish something very similar. Call editableStage, but then create an Sdf.ChangeBlock, and use Sdf APIs on the "edit target layer" rather than using Usd APIs on the Usd.Stage. Using this approach you could create all your prims inside an Sdf.ChangeBlock, end the change block, then use the Usd APIs to author your collection.
Also, there is nothing in USD that can _only_ be done with USD APIs. Because all Usd APIs boil down to calling Sdf APIs in the C++ code. It just may require some investigation and experimentation to figure out what Sdf APIs you need to call to accomplish what the Usd APIs are doing.
.stage() / .editableStage() usage Dec. 17, 2024, 9:57 a.m.
The code there will never hit the "trying to lock a stage that is already locked" warning. Because calling node.inputs().stage() doesn't actually "lock" the stage. It returns the stage for the input node, but immediately releases the lock. So when you then call node.editableStage() later, which does hold onto a lock, you're still safe from the "already locked" warning. If you were to call node.inputs().stage() again after calling node.editableStage(), _then_ you'd get the warning and suffer the poor performance. But you aren't doing that.
So is the second approach to the code still the right one? Yes.
Why? Because the first block of code is very misleading. It gives the impression that "read_stage" and "write_stage" are separate things. But they aren't. As explained in the horizon video, the input node and the python node share a single USD stage. So read_stage and write_stage will be the _same stage_. When you modify write_stage, you are also modifying read_stage. Not fatal, and maybe not even problematic in your node, but misleading.
If you know that each of your edits is guaranteed to be completely independent from all the others, it would be totally fine to do:
```
stage = node.editableStage()
for path in paths:
# Read attribute per prim from stage
# Write: Create References in stage
```
Which is actually identical to your first block of code in terms of behavior, but makes it clear that you are reading from and writing to the same stage. But if there is any chance that one edit will affect the "read" of a subsequent edit, then this may not be a good way to go.
I'll also say that the pure python part of reading a bunch of stuff and putting it into a dictionary from which you later read the values to apply the write operations will take an inconsequentially small amount of time. 99% of the time to run your python LOP will be in the bit where you are creating the references, regardless of how you structure the rest of the code (don't believe me on this - measure it, because I may be wrong).
If you really want to make your node faster, figure out how to use the Sdf APIs on the node.editableLayer() instead of using Usd APIs on the write_stage. Especially if you're creating a lot of prims, this will make a huge difference. If you use this approach, you can use the new node.uneditableStage() method (added in 20.5.403) after calling editableLayer(). This will give you access to a readable stage that will be unaffected by the Sdf edits you make to the editableLayer.
So is the second approach to the code still the right one? Yes.
Why? Because the first block of code is very misleading. It gives the impression that "read_stage" and "write_stage" are separate things. But they aren't. As explained in the horizon video, the input node and the python node share a single USD stage. So read_stage and write_stage will be the _same stage_. When you modify write_stage, you are also modifying read_stage. Not fatal, and maybe not even problematic in your node, but misleading.
If you know that each of your edits is guaranteed to be completely independent from all the others, it would be totally fine to do:
```
stage = node.editableStage()
for path in paths:
# Read attribute per prim from stage
# Write: Create References in stage
```
Which is actually identical to your first block of code in terms of behavior, but makes it clear that you are reading from and writing to the same stage. But if there is any chance that one edit will affect the "read" of a subsequent edit, then this may not be a good way to go.
I'll also say that the pure python part of reading a bunch of stuff and putting it into a dictionary from which you later read the values to apply the write operations will take an inconsequentially small amount of time. 99% of the time to run your python LOP will be in the bit where you are creating the references, regardless of how you structure the rest of the code (don't believe me on this - measure it, because I may be wrong).
If you really want to make your node faster, figure out how to use the Sdf APIs on the node.editableLayer() instead of using Usd APIs on the write_stage. Especially if you're creating a lot of prims, this will make a huge difference. If you use this approach, you can use the new node.uneditableStage() method (added in 20.5.403) after calling editableLayer(). This will give you access to a readable stage that will be unaffected by the Sdf edits you make to the editableLayer.
Faster render times depending on geometry type? Nov. 14, 2024, 1:43 p.m.
There is going to be some additional time to load files like fbx or obj, translate those files into equivalent SOP form then USD form, running the LOP nodes... But this time is going to be pretty inconsequential compared to the time spent actually rendering.
So I'd advise doing the thing that makes the user workflow as smooth as it can be. Having to pre-convert source data into USD files, or pre-cache lights into a USD file are annoying extra steps for the user (or for you while you work on this HDA) which will cost way more time than doing the geo translation and light creation "just in time".
This balance may switch if the geometry is incredibly complicated. Of course the more complicated the data the longer the render takes, so it's still a small percentage of the time spent. But this time may become noticeable to the user. So don't actually trust anything I say. Measure how long these various steps take with your actual data.
So I'd advise doing the thing that makes the user workflow as smooth as it can be. Having to pre-convert source data into USD files, or pre-cache lights into a USD file are annoying extra steps for the user (or for you while you work on this HDA) which will cost way more time than doing the geo translation and light creation "just in time".
This balance may switch if the geometry is incredibly complicated. Of course the more complicated the data the longer the render takes, so it's still a small percentage of the time spent. But this time may become noticeable to the user. So don't actually trust anything I say. Measure how long these various steps take with your actual data.