Jump to content

How to add a Normal attribute in a Python SOP?


magneto

Recommended Posts

I know how to add attributes in Python but it doesn't work for the normal attribute. I add it using this line:

att = geo.addAttrib ( hou.attribType.Point, "N", ( 0.0, 1.0, 0.0 ) )

but when I do this, I can't see the normals in the viewport (show normals toggle on).

I then added a normal attribute using the Point SOP, and now I have 2 N[3] which the detail view show as follows:

N[0] N[1] N[2] N[x] N[y] N[z]

where mines are the first 3, and Point SOP added the last 3.

The docs say Houdini supports attributes with the same name but different type but I am not sure how to set the right type of the normal attribute through Python.

Any ideas?

Thanks :)

Link to comment
Share on other sites

Also should I ensure the values I store are normalized or would the scale be important for potential other tasks?

I have seen a nurbs curve modified by VEX where the length of the point normals vary by the distance between the points.

Which one would be more preferred?

Link to comment
Share on other sites

It's really up to you what you want to put in there. In the case of 'N', while it is generally a normalized value there is nothing stopping you from scaling it up or down using any of many tools in Houdini. It all depends on what you want to do with it later, if anything. Really all the option means is that it will transform the vector when you transform the geometry, as opposed to not doing anything at all if it is just a 3 float attribute.

Link to comment
Share on other sites

Really all the option means is that it will transform the vector when you transform the geometry, as opposed to not doing anything at all if it is just a 3 float attribute.

Interesting. I had the impression that the following applies here:

float[3] doesn't get transformed

vectors[3] get transformed

normals get transformed, but differently and that's what this option is for.

Normal vectors don't transform in the same way as vertices, or position vectors. Mathematically, it's better to think of normal vectors not as vectors, but as planes perpendicular to those vectors. Then, the transformation rules for normal vectors are described by the transformation rules for perpendicular planes.

http://fly.cc.fer.hr/~unreal/theredbook/appendixg.html

Like transformVOP allows you to specify how to interpret the data:

How to treat the values in the 3D entity value parameter: as a position, direction vector, or normal.
Link to comment
Share on other sites

In Houdini 11, all vector attributes will be transformed as a normal and there no way to differentiate between a vector and a normal.

From the HDK docs:

GB_ATTRIB_VECTOR

This attribute is stored as 3 single precision floats. The difference between this and a GB_ATTRIB_FLOAT of 3 floats is that a GB_ATTRIB_VECTOR attribute will be transformed as a normal when the geometry has a transform applied.

http://www.sidefx.com/docs/hdk11.1/hdk_geometry_intro.html#HDK_Geometry_Intro_Attribute_Types

  • Like 1
Link to comment
Share on other sites

Thanks guys, I went with the normalized. Also in my case the vectors are already unit vectors, so I didn't have to normalize.

But if I did, I would have to create intermediate hou.Vector3 values from my nx, ny, nz and then normalize it, and then create a tuple from the members of this vector, right?

setAttribValue doesn't seem to accept hou.Vector3 values according to docs.

Just thought this would be alot of overhead, if I could just pass my vectors. But this is a theoretical question because I don't need to do this right now :D

Link to comment
Share on other sites

You can pass a hou.Vector3 if you have one. For cases where it wants multiple values, a tuple, list or a hou.Vector object at all valid. Something like this:

v = hou.Vector3(point.attribValue("N"))
v = v.normalized()
point.setAttribValue("N", v)

Edited by graham
  • Like 1
Link to comment
Share on other sites

Thanks Graham, that's sweet. Also I noticed in your last line you pass the attribute as a string. Is it safe to do that? I assume you still have to create an attribute for N before that. But if there are 2 N attributes; one as floats and the other as a vector, would that call know which to set?

Anyway was just curious :D

Link to comment
Share on other sites

Yes, that assumes you have an 'N' point attribute.

A better method would be to to pass a hou.Attrib instead of the string name.

normal_attr = geo.findPointAttrib("N")
v = hou.Vector3(point.attribValue(normal_attr))
v = v.normalized()
point.setAttribValue(normal_attr, v)

While this gives the same result as before, using the actual object can be quicker if you are doing the operation over many points/prims/vertices, as it doesn't need to find the attribute from the name every time.

As to what would happen if you had 2 'N' attributes, I can't say exactly. My suggestion would be to not have 2 of them so there is no doubt.

Edited by graham
  • Like 1
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...