Can't access to the custom attribute from group node.

   2249   7   0
User Avatar
Member
8 posts
Joined: Nov. 2019
Offline
Hi,

I created a custom attribute by using Attribute Wrangle node, it runs over the primitives and I can see the attribute in the Geometry Spreadsheet.

Then I try to access this attribute within the "Group Node"'s "Keep By Normal" section to set the spread angle value but it always reads the attribute as 0. I tried the Attribute Wrangle and Group Create node for each attribute classes but nothing changed.

But when I run over the attribute wrangler as "Detail" and use the custom attribute in the transform node, it works. I couldn't understand the issue. Is there a limitation for using custom attributes within the group node?
User Avatar
Member
8 posts
Joined: Nov. 2019
Offline
If I understood correctly some nodes do not support local variables and I found the solution on Reddit.

You can check the link for discussion: https://www.reddit.com/r/Houdini/comments/vrf7xp/local_variable_not_found_in_copy_and_transform/ [www.reddit.com]

Solution:
Use this expression with the attribute name you want to access:
detail(opinputpath('.', 0), 'my_attribute_name', 0)
Edited by Hazart - July 7, 2022 10:07:45
User Avatar
Member
42 posts
Joined: March 2019
Offline
Hazart
Hi,

I created a custom attribute by using Attribute Wrangle node, it runs over the primitives and I can see the attribute in the Geometry Spreadsheet.

Then I try to access this attribute within the "Group Node"'s "Keep By Normal" section to set the spread angle value but it always reads the attribute as 0. I tried the Attribute Wrangle and Group Create node for each attribute classes but nothing changed.

But when I run over the attribute wrangler as "Detail" and use the custom attribute in the transform node, it works. I couldn't understand the issue. Is there a limitation for using custom attributes within the group node?

Maybe you accessed a primnum where the attribute is Zero? Hard to tell if we don't know how you defined the attribute and how you accessed it.
User Avatar
Member
8 posts
Joined: Nov. 2019
Offline
I prepared another quick demo and sending 3 screenshots to describe the details.

In this demo I have a box and I try to choose one side of the box according to the normal directions that I set dynamically by using vex and custom attribute. But it doesn't work with the first approach I tried.

Screenshot Descriptions:

1. You can see the vex code and my node graph. I use the "orientation" parameter that I defined within my hda.
2. You can see the Group node details and my implementation.
3. You can see the Geometry Spreadsheet and the warning messages that my Group node gives.


Note: I'm beginner to the Houdini therefore my approach may not be suitable but anyway I'd like to know the limitations and other approaches.

Thanks.

Attachments:
1.png (4.1 MB)
2.png (3.9 MB)
3.png (1.8 MB)

User Avatar
Member
166 posts
Joined: March 2014
Offline
It's very rare that a node allows you to use the @ notation to specify values. An exception would be for example the polywire node.

It looks like the group node lets you only pick one global direction, not a direction per-primitive. If you wanted to group each primitive based on a direction that's different for each primitive, you'd have to do the grouping yourself:
if (degrees(acos(dot(v@N, v@targetDirection))) < ch("maxAllowedAngle")) // vectors must be normalized
    i@group_MyPrimitiveGroup = 1; // Houdini will create this group for you when you use group_

You would normally want to store your values as a vector attribute. Instead of assigning three floats, you'd just assign one vector:
v@targetDirection = set(0, 0, 1);

When you want to read it, the expression (prim or detail) allows you to specify which component to get, it's the last parameter. 0 is x, 1 is y, 2 is z. To get the y of targetDirection:
detail(0, "targetDirection", 1)

And note how you don't need to use opinputpath if you're grabbing an attribute from the incoming node. You can just specify the number of input port.
Edited by Digipiction - July 8, 2022 04:54:39
User Avatar
Member
8 posts
Joined: Nov. 2019
Offline
Hi Digipiction,

Thank you so much for your very detailed answer and tips. Especially the first and the last code samples caught my attention. To really understand the first code I started to study trigonometry again, I have very limited knowledge of trigonometry and whenever I see something like the code you wrote I get confused and I notice that I have to study it. Your post gave me a motivation to start learning trigonometry again Thank you so much. I'll try your code samples.
User Avatar
Member
166 posts
Joined: March 2014
Offline
Hazart
To really understand the first code I started to study trigonometry again
I don't know too much about it myself, the majority of what I know comes from a tutorial I watched years ago on the unit circle (a 2D circle with a radius of 1). I had forgotten all about it since school, but this simple refresher has come in handy many many times over the years, for example when wanting to draw a spiral, or also in this case.

You have two vectors and want to find the angle between them. In your head you visualize the 2D unit circle centered on the origin of an XY grid. You assume that one of the vectors points from the origin along the positive X-axis.

Now we have a second vector, let's say it points from the origin to the top left (positive Y, negative X). The dot product gives us the projection of one vector onto another. Since our first vector points along the X axis, the projection in this case is onto the X axis, and the result of the dot product is simply the second vector's X-coordinate.

This value will be negative, because we said that the second vector points to the top left, i.e. to the left of the Y-axis, i.e. negative. This also quickly shows that a positive dot product means that the vectors have an angle less than 90 degrees, while a negative dot product means that they have an angle greater than 90 degrees. It also shows us that the dot product can only differentiate up to 180 degrees, because it only differentiates between "left of the Y axis" and "right of the Y axis".

The cosine on the unit circle works like this: you start on the unit circle at the coordinate X=1, Y=0 and travel counter-clockwise along the unit circle. You stop at your target destination and read the X-coordinate of that point, that's your cosine. However, we already calculated the X-coordinate, we want to do the reverse. And the reverse of cos is the acos function.

So acos(dot) gives us the angle between the vectors in radians. The degrees() function simply converts radians into degrees. Radians are just a different unit to describe angles: if you travel half a unit circle, that's PI radians. If you travel along a full unit circle, that's 2 PI radians. Which makes sense, because the circumference of a circle is 2*PI*radius, and with the unit circle having a radius of exactly 1, that gives 2 PI as its circumference.
User Avatar
Member
4643 posts
Joined: Feb. 2012
Offline
Hazart
Hi Digipiction,

Thank you so much for your very detailed answer and tips. Especially the first and the last code samples caught my attention. To really understand the first code I started to study trigonometry again, I have very limited knowledge of trigonometry and whenever I see something like the code you wrote I get confused and I notice that I have to study it. Your post gave me a motivation to start learning trigonometry again Thank you so much. I'll try your code samples.

Would recommend Keenan Crane amazing series also if you want to deep dive/refresher:

Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]

youtube.com/@pragmaticvfx | patreon.com/animatrix | pragmaticvfx.gumroad.com
  • Quick Links