How to reference @ptnum in a point() Expression Function

   2908   11   2
User Avatar
Member
26 posts
Joined: Nov. 2021
Offline
Hello dear Houdini community, here I come with what I guess is some “silly” problem, but to which I don’t know what else to try to find a workaround.

Ok, so it’s basically around Expression Functions in hscript. I’m trying to feed a local variable to a chramp point value. As far as I understand it’s not possible to reference a local variable in such fashion, in the same Attribute Wrangle, hence you gotta store that local variable as an attribute, in my case as a point attribute, since I’m running a Point Wrangle, and then retrieve it in a following Attribute Wrangle and in it proceed to feed it into a new chramp, etc.

In this next AttributeWrangle, I should be able to retrieve this attribute in a chramp point value, by using the Expression Function point(). Now, here is where I get tangled and don’t… really know what I’m doing wrong.

For reference the point() format is the following:

point(surface_node, point_number, attribute, index)

In consequence I use 0 for surface node, “sample_attribute” for attribute, and 0 for index (since it’s a float). Now, how do I reference the current @ptnum? In theory shouldn’t $PT work? The only option that actually retrieves the attribute data is by manually entering a point number, for ex 24, in what would look as the following

point(0, 24, “sample_attribute”, 0)

But on the other hand, whenever I try with something but a… hardcoded arbitrary point number, I´m not able to retrieve any data. I tried with $PT, with @ptnum, and even with some instancepoint(), which I think it’s not even meant for these instances. I guess the bottom line is… how do I reference the current instanced point in a point() Expression Function.

Thanks in advance for your time and… I’m all ears : )
User Avatar
Member
2041 posts
Joined: Sept. 2015
Offline
"
Manuloti
how do I reference the current instanced point in a point() Expression Function.
You don't...not in a parameter with an expression.(unless it's a single value like a detail attribute).
Otherwise, like you've seen - you specify the specific point number.
Are you thinking that a parameter with an Hscript expression would be running over points like in a wrangle?
So that the expression is applied to each incoming point?

You could in a wrangle apply the chramp to each incoming point.

Posting your hip to show and explain what you are trying to accomplish may help.
Edited by BabaJ - Aug. 25, 2023 13:23:00
User Avatar
Member
26 posts
Joined: Nov. 2021
Offline
Ok, so… I prepared a "test.hip" file with an isolated proof case where I emulate the actual situation I´m facing. I attached it to this post, but first let me lay it down here.

I essentially want to build “cohesive” geometry between two or more rings. These rings have points with dissimilar values of @P in all the 3 axis, as they are originally the bevel of holes made to a sine waved surface, hence they are noisy in the @P. My approach is to… find whatever points from these rings face at each other, within a range, and initially build an array of points, as steps between the two points, depending on how far from each other are they. Then… with these new points build quads (hopefully), etc. To consolidate these isolated rings with one centered patch that acts as a bridge.


1.



These are the two rings, with vector pointing outwards in each point. Then I use a pccone() to find pair point from the opposed ring.



2.



For each point with a pair, I average the position between the two rings, to generate an pivoting position.




3.



Let’s say pt0 finds pt1.



4.



From this pair I find an @axis vector, which I’ll use later on to rotate on and place the steps, and @dir vector which is towards where the steps will be oriented to.

And this is where I find my inconvenience. My idea is to interpolate the angle between the direction to the pt0 and pt1 with a slerp(). But I need the distance from the pivoting position of that steeped pt to surf between 3 values, depending on the bias (0-1) used in the slerp().
If the bias is 0, the distance from the pivoting position should is the one to pt0, if the bias is 1, the distance from the pivoting position should is the one to pt1, and if it’s 0.5, the distance should be the average of pt1 and pt0 positions, plus… some offset in such direction, depending of the distance of this average position to the pivoting position, etc.

So here it is, to interpolate a value between 3 targets.
If I wanted a linear transition between pt1 and pt0, sure, no issue, I’d do a fit01() with the slerp bias value, where 0 is the distance to pt0 and 1 the distance to pt1. Now… if I want to tame, to shape that transition, that mid-state with some factors in consideration, how do I achieve that. That’s why I thought of a chramp() to shape that distance value as the slerp bias evolves. For that I'd need to feed the target distance value in the position 0, the 0.5, and the 1, accordingly. But… to do that I’d need to be able to feed the stored distances in the ramps values and… I don’t know how, or if as you say, is even possible.


___


FILE NOTES:

The final result is at the point wrangle in yellow, which is only running on one point, so it can better illustrate this idea I described.

_

The stored distances are:

f@to_org_pt_vector_lenght
f@to_avg_pos_pts_lenght
f@to_found_pt_vector_lenght

These are the ones I’d like to feed to each position of the slerp bias in the chramp. Now the values in that ramp are arbitrary.

_

The displayed polylines are for illustrative purposes only.



___


I tried to be give you a clear enough context for what I'm looking for and why is that, although I don't know if I've been able to achieve it. If anyone has questions, please let me know.

Thanks for time : ) .





_
Edited by Manuloti - Aug. 25, 2023 20:39:33

Attachments:
1.jpg (13.5 KB)
2.jpg (13.7 KB)
3.jpg (18.3 KB)
4.jpg (19.4 KB)
test.hip (221.1 KB)

User Avatar
Member
475 posts
Joined: July 2005
Offline
Not sure if I got your point correctly, but if you want to rotate a point to another point around a center with ramp control, you may want have control over the scale between the points and the center. So if the scale is different you can interpolate it and/or can add extra scale aswell.

Here is an example
Edited by Aizatulin - Aug. 26, 2023 04:05:36

Attachments:
chramp_rotate.hipnc (165.5 KB)

User Avatar
Member
26 posts
Joined: Nov. 2021
Offline
Yes! that example seems to do what I was aiming for. After posting my example I... realize I wasn't gaining much from trying to do it in the way I was. Being confused doesn't do us any good. But back to yours, what I don't understand is how a different value of that ramp (well, both ramps) is being instanced at each point cycle.

vector rotate_chramp(vector A,B,C; float u){...}

Firstmost, this is something I'm not familiarized with; that way of inicialzing. But most importantly, that float u is the one that acts as the "rampos" in the chramps, and I guess it takes from the @ptnum to indicate the "current position in the ramp"? . I could imagine fitting the @ptnum from 0 and the @numpt, to a 0-1, so the chramp can read that value, but I would be facing again the same hurdle I came here with, but this doesn't take place in your code, yet! It works correctly xD. How does the float u evolved in value across the Point Wrangle? I'm missing a part of the movie.

Thanks for taking the time to evaluate my case and even make an example for me to review : ) .

_

Ultemately, for anyone wondering about the initial question I made, I think the answer is pretty much... "no, you can't reference an attribute from the current instanced point in a chramp parameter"
User Avatar
Member
475 posts
Joined: July 2005
Offline
In my example "rotate_chramp" is a function which takes 3 vectors "A,B,C" and a float value "u". In the last line the function evaluates the three given points from the second input and the "curveu" value of the first input, which was calculated by the resample node. So usually each point has a curveu value between 0 and 1 corresponding to its point number.
The first ramp "interpolate" takes the u (between) 0 and 1 and it is called by lerp(lA, lB, ...), which means, whenever your ramp is close to the zero, the length is close to lA and on the other side the same for lB and one. Ideally your the ramp starts from 0 and ends at 1. The second ramp is just an additional length, which can be set zero by default (I think can be ignored in your case).
User Avatar
Member
2041 posts
Joined: Sept. 2015
Offline
Manuloti
"no, you can't reference an attribute from the current instanced point in a chramp parameter"

But you can in a wrangle, reference an attribute per point with the same chramp parameter.

Attachments:
Chramp_per_pt.hiplc (140.3 KB)

User Avatar
Member
26 posts
Joined: Nov. 2021
Offline
Oh! I see now. @curveu is like... @uv.x whenever you apply a UV texture to a line and get a float value for each point present in the line, across its evolution. I ignored you could obtain it from a Resample node. And it's with that attribute you feed the "amount" argument in the lerp, I see.

The rotation I settled it with a slerp between the target quaternions, accounting the rotation between the v@dir I made, to both vectors that formed the angle and rotating the v@dir itself. When... looking at your example, it's crystal clear how I like to over complicate things, when it's way easier "mentally" to just rotate one of the vectors, along the scaled angle value formed between the two vectors.

I now also see why

BabaJ
But you can in a wrangle, reference an attribute per point with the same chramp parameter.

Instead I was trying to do it in the very parameter of the chramp, when indeed I could just use a lerp between the two target distances, and modulate it with the "amount" parameter in the VEX function itself. I guess I really didn't have in mind what lerp amounted for (not pun intended) and... got tangled in seeking a solution in Hscript muddy waters xD.

I personally don't work with matrix approaches "first", cause like any God fearing simple human they tend to intimidate me xD, but... in this example it's helps in order to see the "step by step" of the vector, from basic ident matrix, to be rotated and then displaced along. What I still don't incorporate is... how a "float u" is connected to the previously present f@curveu, without any "u = f@curveu", but that's anecdotal at this point xD.

__

Anyway, thanks both, I'll put this to work on Monday and see if I can make good use of it.

Noted: no need to reference an attribute from the current instanced point in a chramp parameter, when you can use a lerp and work with its "amount" argument.

Again, many thanks for the time and patience : )
User Avatar
Member
475 posts
Joined: July 2005
Offline
,

@Manuloti, don't get confused by the @curveu attribute, it is just an example to vizualize the path of the rotation. The function itseld doesn't care what you put in as parameters as long it is a float attribute. You can put in any float value and for the function it is always "u". So yes internally the function is creating a reference like (u = f@curveu) and if you manipulate u the parameter (f@curveu) changes aswell (if it is not a constant value like number of course).
But this is the great advantage of using functions. You are independent from context.
User Avatar
Member
26 posts
Joined: Nov. 2021
Offline
I mean, I get @curveu role in the procedure. I myself, since I didn't have any pre-existing geometry, I got my "0-1" value from dividing the total angle between the vectors, by an arbitrary value I used as a step, hence I... controlled the number of iterations (generated points) and the by adjusting that "current angle" in the the total angle range, I got my "rampos", or "u" in your example. I added some other goodies (using the blessed lerps xD) to "tame" it a little bit further to my taste (depending on the situation), and now I'm... generating the quads between the lines, but so far it looks like this, and I'm really happy about it.



Now, what I don't get, it's the... semantics in "how is it possible @curveu is evaluated if it appears after the chramp()". I don't come from a coding background (from graphics, not even computer graphics), so I don't "return P" xD, or declare "vector rotate_chramp(vector A,B,C; float u)". I was wondering if that was a vector4, but I don't think so, I guess it’s just another way of declaring the variables, etc. Is just… my flagrant ignorance on C, C++, Python and "all the above". For what is worth, VEX is the first "coding" language I do a relative deep dive in, nearly 2yrs so far, and mainly out of... the acknowledgement I have to explore it and utilize it daily and thoroughly to come up with solutions for procedural geometry projects.

Anyhow, I'm reaaaally thankful for the guidance : ) .

Attachments:
Screenshot 2023-08-29 195133.png (189.7 KB)

User Avatar
Member
4516 posts
Joined: Feb. 2012
Offline
Manuloti
I mean, I get @curveu role in the procedure. I myself, since I didn't have any pre-existing geometry, I got my "0-1" value from dividing the total angle between the vectors, by an arbitrary value I used as a step, hence I... controlled the number of iterations (generated points) and the by adjusting that "current angle" in the the total angle range, I got my "rampos", or "u" in your example. I added some other goodies (using the blessed lerps xD) to "tame" it a little bit further to my taste (depending on the situation), and now I'm... generating the quads between the lines, but so far it looks like this, and I'm really happy about it.

Image Not Found


Now, what I don't get, it's the... semantics in "how is it possible @curveu is evaluated if it appears after the chramp()". I don't come from a coding background (from graphics, not even computer graphics), so I don't "return P" xD, or declare "vector rotate_chramp(vector A,B,C; float u)". I was wondering if that was a vector4, but I don't think so, I guess it’s just another way of declaring the variables, etc. Is just… my flagrant ignorance on C, C++, Python and "all the above". For what is worth, VEX is the first "coding" language I do a relative deep dive in, nearly 2yrs so far, and mainly out of... the acknowledgement I have to explore it and utilize it daily and thoroughly to come up with solutions for procedural geometry projects.

Anyhow, I'm reaaaally thankful for the guidance : ) .

Hi,

@curveu is just an attribute on the geometry just like a variable declared inside some code that you access, so it doesn't matter if you access it before or after chramp. You are just passing that reference to the chramp function so it can evaluate it per point based on the value stored in curveu attribute on each point.
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 | animatrix2k7.gumroad.com
User Avatar
Member
475 posts
Joined: July 2005
Offline
In addition:
If you don't need an attribute anymore you can delete it (in VEX and there is also a node for it "attibute delete"), but in many cases you don't even have to create one. So if you are in VEX for example, you can also create a local variable without @, which lives only during evaluation (and not longer) until you have the result you want. Attributes are useful, if you want have access multiple times from different nodes (without recalculating the value every time).
  • Quick Links