Jump to content
dzigakaiser

Python Shelf Tool -> Is adding point attributes possible?

Recommended Posts

Posted (edited)

Hey guys,

 

I am currently stuck with a tool I am writing. I have a json file that contains data from Clarisse and I wrote a shelf tool that re-creates Clarisse's scatter in Houdini. 

I went the path of creating an Add SOP with the python script with all the points from Clarisse and their position data, a few Attribute Create SOPs, CopyToPoints SOP and the asset file.

Now I need to add my orient attribute to the points based on the XYZ rotation that is saved in the json. 

The problem I encounter is that I actually cannot add point attributes via the shelf tool python script, right?

I tried to find a solution to this but as far as I understand, as long as I am not working from a Python SOP or the shell I can only call the geometry() object as read only or freeze() it but then I cannot write the attributes back onto the points(?)

Is there something I misunderstand or another workflow I am missing?

If one you has an idea or solution or other comment, I appreciate it :)

 

Thank you!

Dziga

Edited by dzigakaiser

Share this post


Link to post
Share on other sites
Posted (edited)

You could create a VEX node after the Add sop and wire it in. Then you can assign the @orient attribute inside the code block (snippet) of the newly created VEX node.

wrangle_node  = hou.node("/obj/%s/%s/%s" % (node.parent().parent(), node.parent(),"attribwrangle1"))
if wrangle_node == None:
	# Create a wrangle to define our orient.
	wrangle_node  = node.parent().createNode("attribwrangle","attribwrangle1")
	wrangle_node.parm('snippet').set('@orient = {0,0,0,0};')
	wrangle_node.parm('class').set(1)
	wrangle_node.setInput(0,addsop_node)
	wrangle_node.moveToGoodPosition()

 

Edited by Atom
  • Like 1

Share this post


Link to post
Share on other sites

Hey Atom,

thank you so much for the super quick reply and solution.

I was actually wondering if this is the way to go but wasn't sure yet if there isn't a hidden function somewhere to directly add the attributes and to what extend I can put code into the wrangle via script^^

Always more to learn! I am going to try this wrangle method right away.

brb

Dziga

Share this post


Link to post
Share on other sites
Posted (edited)

Hey again,

it works! But, I think I made a mistake in my thinking :0 This is basically the same result as using the Attribute Create SOP atm (only holding one orient value for all points).

I assume, I would need to actually read from the json again inside the wrangle to get the stored per point data? Or create the inital points by using a wrangle instead of the Add SOP (this maybe makes the most sense)?

I was hoping, since I already go through the json for the Add SOP and the position data inside my script, that there is a way to also grab the rotation data and save it per point.

Do you know of a workflow for this by any chance?

Thanks for the help so far!

Cheers,

Dziga

Edited by dzigakaiser

Share this post


Link to post
Share on other sites

I think it is possible in pure python. If I remember right, you have to create the attribute on the geometry first. Once the .geo() knows about the existence of the attributes you can set values on the points.
 

attrib_Cd = geo.addAttrib(hou.attribType.Point, "Cd", (1.0,1.0,1.0))
height_attrib = geo.addAttrib(hou.attribType.Point, "dem_height", 0.0)
now_lat_attrib = geo.addAttrib(hou.attribType.Point, "now_latitude", 0.0)
now_long_attrib = geo.addAttrib(hou.attribType.Point, "now_longitude", 0.0)

# Create the point
pt0 = geo.createPoint()
pt0.setPosition(hou.Vector3(X,Y,Z))
if color_min: 
	pt0.setAttribValue(attrib_Cd, (0.0,0.0,0.5))
if color_max: 
	pt0.setAttribValue(attrib_Cd, (0.5,0.0,0.0))
# Store data_height, now_lat and now long with this point.
pt0.setAttribValue(height_attrib, data_height)
pt0.setAttribValue(now_lat_attrib, float(now_lat))
pt0.setAttribValue(now_long_attrib, float(now_long))

 

  • Like 1

Share this post


Link to post
Share on other sites

Thanks again for the elaborate reply. I am not sure how I would go about it in my case.

Right now, the python script creates an Add Sop and when I try .addAttrib I get an error that the geometry is read only.

Or is this the example for using a Python SOP? Sorry, I am a bit confused ^^

I think for now, I will try a workaround by storing my other attributes in separate Add SOPs and then copy the P attrib of those into the correct attributes onto my main points.

Not very nice to look at but might be the only thing I am currently able to throw together :s

Share this post


Link to post
Share on other sites

What if, instead of creating an AddSop, you create a Python SOP and install the above code? The code can read from your file and create the point and attribute at the same time.

def code ():
"""
import os,re,random

node = hou.pwd()
geo = node.geometry()
attrib_orient = geo.addAttrib(hou.attribType.Point, "orient", {0,0,0,0})

# Create the point
pt0 = geo.createPoint()

# INSERT CODE TO READ XYZ and python_orient from file.
pt0.setPosition(hou.Vector3(X,Y,Z))

# Store data_height, now_lat and now long with this point.
pt0.setAttribValue(attrib_orient, python_orient)
"""

# Create python sop and populater code box with code from the def, up above.
node_python = node_geo.createNode("python")
if node_python != None:
	# Install code that will detect and create materials from shop_materialpath.
	node_python.parm("python").set(code.__doc__)

 

  • Like 1

Share this post


Link to post
Share on other sites

Python SOP or Python based geometry HDA is definitely the way to go

it's really not a good idea to use Add SOP with thousands of parameters if you are reading in thoudands of points from your custom data file, also baking in the data is a big disadvantage, Python SOP can read your file live and you can always use Stash SOP after to store the geo in the file if you really want that

you can also have a look at the Table Import SOP which is an example of Python Based HDA, so you can have a look at the code section to see how it works

  • Like 1

Share this post


Link to post
Share on other sites

Thanks both of you. I understand the approach much better now. I think I might rewrite it over the weekend then before ending in a dead end when dealing with very large amounts of data.

Just to clarify, though, does the Python SOP evaluate once like the shelf tool does or does it evaluate every frame when the nodes cook?

On the one hand, I was wondering in the beginning if using a Python SOP is slower if it reads from the .json every frame. On the other hand, it includes live updates to the scene data then which is actually more valuable in most cases.

As overwhelming as it is sometimes, especially not having a programming background, it is awesome to see how deep you can dive and how much there is to learn! 

 

Share this post


Link to post
Share on other sites
9 hours ago, dzigakaiser said:

does the Python SOP evaluate once like the shelf tool does or does it evaluate every frame when the nodes cook?

it evaluates when something dirties the node, like if the inputs or parameters change or are time dependent

9 hours ago, dzigakaiser said:

I was wondering in the beginning if using a Python SOP is slower if it reads from the .json every frame

if it's not time dependent it will only cook once, not every frame, but also you can lock the geo using Stash SOP or save to disk (.abc, .usd, ...) and load back in, so that even if it's animated it will be faster than loading custom format using python

Edited by anim
  • Like 1

Share this post


Link to post
Share on other sites

Okay, perfect! Sounds like the way to go then. I am going to try it this weekend. Thank you again for all the help and patience!

One more small thing if I may ask. Not directly to this but something I encountered in the current tool.

I transferred the scale data to the points prior to instancing and the scale affects the orientation of the instances. Could it be connected to a different order of translate, rotate, scale in Houdini compared to Clarisse?

I cannot really see what order Clarisse is using in the scatterer and I am not sure what Houdini is using. 

Or might this be connected to a different issue altogether?

Oh and one other thing. I just tried the code above to define the code and create a Python SOP containing it.

If I don't indent the block of code in the definition I get a syntax error because it expects an indented block, when indenting the definition the Python SOP fails to cook because it gets an unexpected indent.

I am sure there is a simple fix to this that I can't think of right now, isn't there?^^ I would greatly appreciate a small hint.

Edit: found textwrap.dedent for the indentation issue:)

Have a nice weekend!

Dziga

Edited by dzigakaiser

Share this post


Link to post
Share on other sites

Okay guys,

one more time: thank you!! I rewrote it over the weekend (two times:P) and the performance and flexibility is so much better compared to before. 

Time to build some matrices and then it should work^^

Have a nice week!

Dziga

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×