Jump to content

Merge individual points from 2nd input?


aghourab

Recommended Posts

A little problem that has been bugging me over the weekend is point sorting in a python sop. I'm aware that this functionality doesn't currently exist, but I have managed to create a hack that allows me to do so.

The problem at the moment is that it can be quite slow. 2 seconds per 1000 points to be precise, which hurts a little (or a lot of you need it to cook every frame, doh!).

My current implementation is to create a dictionary of {points : attributeToSortTo}, delete all points, then merge in points in the correct order from a second input. It appears I cannot merge in individual points, so I'm forced to use geo.merge() in combination with a blast sop (i promote the point number i'm interested, blast all non selected, then merge it in).

I'm wondering if there's a method to import individual points, or failing that, some speed tips!

Attached scene file and otl for python sop.

sortFromAttrib.zip

Link to comment
Share on other sites

I'm surprised it even works at all, for a few reasons. That being said, I don't see there being a good way to actually do this with Python that would be fast unless you use inlinecpp. My test using an inlinecpp function was able to sort a huge amount of points in virtually no time.

Since it technically works but is just slow, looking at your code you could potentially increase speed by using geo.poins()/prims() instead of iterPoints()/iterPrims() since the full element methods are generally a bit faster when iterating. Also, instead of directly calling attribValue(attrib_name), get a hou.Attrib object before hand and pass that instead of the name. This results in faster attribute table lookup times since it already has a reference to the actual attribute and doesn't have to look it up for each element.

You could also construct your dictionary by using hou.Geometry.pointFloatAttribValue()/primFloatAttribValues() and zipping that with a range the size of your points/prims. It's much faster for Houdini to get all the values at once than to get them one at a time.

The reasons I'm surprised it actually works are as follows:

- You communicate with the blast by setting a parameter on the Python SOP multiple times while it is cooking; this is bad. It's always a bad idea to set any parm on a node from the node's cooking code because it can lead to undefined results since parm changes can lead to node recooking. This doesn't seem to break in this instance probably due to the fact that your Python SOP has no parm dependency on that parm within it's cook code.

- Sort of in line with the previous comment, you're effectively changing the incoming geometry, which I'm surprised isn't causing cooking problems with the Python SOP since I would have figured it would have input changed dependencies for the 2nd input geometry.

- You define your ordered point numbers as a result of the order in which your dictionary is iterated over. Since dictionaries aren't an actual ordered item, I'd be weary of this. This seems to work due to the fact the keys are all simple integers.

Edited by graham
Link to comment
Share on other sites

Since it technically works but is just slow, looking at your code you could potentially increase speed by using geo.poins()/prims() instead of iterPoints()/iterPrims() since the full element methods are generally a bit faster when iterating. Also, instead of directly calling attribValue(attrib_name), get a hou.Attrib object before hand and pass that instead of the name. This results in faster attribute table lookup times since it already has a reference to the actual attribute and doesn't have to look it up for each element.

Cheers for the speed up help. Its a shame I cannot import individual points, as that would allow me to circumvent the use of the inline CPP which I am not yet familiar with.

The reasons I'm surprised it actually works are as follows:

- You communicate with the blast by setting a parameter on the Python SOP multiple times while it is cooking; this is bad. It's always a bad idea to set any parm on a node from the node's cooking code because it can lead to undefined results since parm changes can lead to node recooking. This doesn't seem to break in this instance probably due to the fact that your Python SOP has no parm dependency on that parm within it's cook code.

- Sort of in line with the previous comment, you're effectively changing the incoming geometry, which I'm surprised isn't causing cooking problems with the Python SOP since I would have figured it would have input changed dependencies for the 2nd input geometry.

- You define your ordered point numbers as a result of the order in which your dictionary is iterated over. Since dictionaries aren't an actual ordered item, I'd be weary of this. This seems to work due to the fact the keys are all simple integers.

I was surprised to find the dictionary ordered. I understand that inherently they have no order, so I was going to use a sort method, but it seemed to work. It all cooks now, but its the kind of thing where, as you mentioned, is so flakey it will most likely cause issues in the long run. I'll have a look at the inline cpp, and see if I can get it working.

Thanks for the help Graham!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...