duplicatePointSource() and generating new geometry [SOLVED]

   3111   8   2
User Avatar
Member
183 posts
Joined: Dec. 2011
Offline
So I am currently trying to teach myself HDK so sorry for my noobishness in advance. I am writing a node that takes input points and reads attributes from them to generate an entirely new piece of geometry. At the end of the cook process all input geometry is discarded rather than passed on. My question is if I should be using duplicatePointSource() in this sort of scenario?
Edited by - Feb. 5, 2015 10:46:11
User Avatar
Member
1743 posts
Joined: March 2012
Offline
90ender
So I am currently trying to teach myself HDK so sorry for my noobishness in advance.
No worries! Feel free to ask lots of questions.

I am writing a node that takes input points and reads attributes from them to generate an entirely new piece of geometry. At the end of the cook process all input geometry is discarded rather than passed on. My question is if I should be using duplicatePointSource() in this sort of scenario?
Nope. If you don't need any of the input geometry to be copied into the output, you don't need to call duplicateSource of any kind. You should be able to just read the relevant data from the input geometry.

However, you should be aware that gdp may not be empty at the start of a cook. If the geometry generated on the SOP's previous cook hasn't been evicted from the cache, it will contain the previous cook's output geometry, else it will be a fresh detail. Most SOPs that don't copy their input geometry, e.g. the new Scatter SOP, just call gdp->clearAndDestroy(); to make sure that the detail is empty.

In some cases, it's possible to reuse the previous cook's geometry if you know that you can avoid extra work that way, e.g. in the SOP_CopRaster HDK example, it can avoid recreating the points, recreating the colour attribute, and setting the point positions, depending on what data is the same as on the previous cook. Of course, that example doesn't have an input to worry about, so it's a bit simpler than if you had to check the unique ID and meta cache count on the input detail to see if it's changed. It can get quite complicated, especially if you have a lot of parameters, so I'd recommend avoiding it until you're a bit more comfortable.
Writing code for fun and profit since... 2005? Wow, I'm getting old.
https://www.youtube.com/channel/UC_HFmdvpe9U2G3OMNViKMEQ [www.youtube.com]
User Avatar
Member
183 posts
Joined: Dec. 2011
Offline
Thanks for the excellent reply ndickson! So if I understand correctly all I need to do is to lock the input and then just read the data from the points? Interesting.

As for keeping geometry instead of recooking every time, unfortunately that seems like something I will eventually have to do in order to optimize the node since it will be used to create large amounts of geometry. For now I will just program it so it recooks every time. Thanks for the note about the SOP_CopRaster though, I'll have to check it out.

For now my only question is, how do I read the input point's attributes without copying them into my node's gdp? Also, what does it mean to ‘bump’ stuff, like “->bumpDataId()”?
User Avatar
Member
183 posts
Joined: Dec. 2011
Offline
Never mind, I've figured it out and it is working like a charm. Thanks for all your help!
User Avatar
Member
1743 posts
Joined: March 2012
Offline
90ender
…I will eventually have to do in order to optimize the node since it will be used to create large amounts of geometry.
What sort of geometry are you building? If it's primarily closed polygon primitives, it might be faster and require less memory if you can use polygon soup primitives instead, which can be built quickly using GU_PrimPolySoup::build.

If you need a lot of separate primitives, you can use gdp->stashAll() before the clearAndDestroy(), and then call gdp->destroyStashed() at the end of the cook. stashAll() will take the chunks of memory for all primitives, put them in a state where they aren't tied to the detail in any way and put them in a big array, so that if you create primitives again, it'll first check the stash for one of the same type, to avoid freeing and reallocating that memory every time. After your code has created all of the primitives it will, calling destroyStashed() will free any primitives that are still in the stash.

If it's almost always the exact same set of primitives as on the last cook, with exactly the same topology, but just with different attributes, for example, and it's easy to check whether that's the case, then it can be a big advantage to use the previous cook's output geometry (if it hasn't been uncached).

For now my only question is, how do I read the input point's attributes without copying them into my node's gdp?
Is that the part you mention you've figured out?

Also, what does it mean to ‘bump’ stuff, like “->bumpDataId()”?
That's an advanced feature that it's not recommended to be used unless it's really necessary. For SOPs that don't copy their inputs, it probably won't give any benefit, unless you have custom caching and the most common reason for recooking is a parameter change instead of the input changing; make sure to remove the line mySopFlags.setManagesDataIds(true); if your code isn't going to manage data IDs itself. All data IDs will be automatically bumped at the end of the cook if that flag isn't set.
Writing code for fun and profit since... 2005? Wow, I'm getting old.
https://www.youtube.com/channel/UC_HFmdvpe9U2G3OMNViKMEQ [www.youtube.com]
User Avatar
Member
183 posts
Joined: Dec. 2011
Offline
The node is for building the base skeleton of tree branches given parent branches as input, so as you can imagine, it's pretty common to end up working with close to a million points. Unfortunately since the geometry generated is open primitives and since it needs to have several point attributes (like pscale, material paths, and such) I don't think using either polygon soups or packed geometry can be used to speed up the process.

So it seems to me that the best way to optimize it would be to avoid recooking all the child branches every time their parent branches are tweaked, unless specific attributes change. That's my guess anyway, as I said I am still rather new to this so any pointers here would be great.

Thanks for the tip about stashing! I will definitely look into how to use it.

I did figure out how to reference geometry from my node's input without copying it into my gdp. Sorry about the vagueness there.

I kind of figured that bumping was for updating changed attributes. What do you mean by managing data IDs? Is this something that is not needed when you are just creating new geometry?
User Avatar
Member
7722 posts
Joined: July 2005
Offline
To avoid redoing work for inputs that haven't changed, you can make use of SOP_Node::useInputSource().
User Avatar
Member
183 posts
Joined: Dec. 2011
Offline
So you're saying that it allows you to read input geometry without forcing it to recook? Does that mean you don't need to lock the inputs?
User Avatar
Member
7722 posts
Joined: July 2005
Offline
No, you have to cook the input by locking it if you want to read its geometry. This is because may have already been swapped out of the internal geometry cache. But if useInputSource() says that it hasn't changed from the last time you called it (ie. last time you cooked), then you don't need to read that input, nor redo any of the work associated with that input for your output.
  • Quick Links