How to create unevenly distributed points along a curve?
5048 17 3- GlenD
- Member
- 118 posts
- Joined: 12月 2013
- Offline
Hello everyone, I have an issue with creating a line that has non uniform distribution of points. I created an initial Line 1 and then resampled the line based on a set length. I have been trying to find a solution that would allow me to resample each line segment based on a different length each time and match Line 2.
At the moment I have tried recreating the line using a point wrangle that creates a point from the last point based on the new length and then create line based on the new points. This keeps going until all the points from the original have been calculated. It works some of the time.
Has anyone solved something similar to this that would be easier than the previous mentioned solution?
Thanks!
At the moment I have tried recreating the line using a point wrangle that creates a point from the last point based on the new length and then create line based on the new points. This keeps going until all the points from the original have been calculated. It works some of the time.
Has anyone solved something similar to this that would be easier than the previous mentioned solution?
Thanks!
Edited by GlenD - 2023年2月14日 05:23:14
- lll_jnrk
- Member
- 4 posts
- Joined: 10月 2019
- Offline
Hi GlenD
i´m not 100% shure i understood your question right, but i think what you are looking for is primuv()...
you can easily sample positions on a given line or curve with primuv(), and thus could also randomize the positions..
example with a chramp to bias the point positions:
in a wrangle (over detail):
for(int i = 0; i< chi("num"); i++){
float bias = ch("end")/(chi("num")-1)*i;
vector u = set(chramp("rmp",bias),0,0);
vector pos = primuv(1,"P",0,u);
int p = addpoint(0,pos);
}
hope that helps
best
jan
i´m not 100% shure i understood your question right, but i think what you are looking for is primuv()...
you can easily sample positions on a given line or curve with primuv(), and thus could also randomize the positions..
example with a chramp to bias the point positions:
in a wrangle (over detail):
for(int i = 0; i< chi("num"); i++){
float bias = ch("end")/(chi("num")-1)*i;
vector u = set(chramp("rmp",bias),0,0);
vector pos = primuv(1,"P",0,u);
int p = addpoint(0,pos);
}
hope that helps
best
jan
- GlenD
- Member
- 118 posts
- Joined: 12月 2013
- Offline
Thanks, I'll check it out!
I basically have 3 different pieces of geometry that are pipes with varying length. They are copied to the points and overlap each other due to the different lengths. The end goal is to copy the different pipes, which are being copied using the @piecenum attribute and then have them fit together.
I have accomplished this in Unreal using Blueprints, this time it has to be completed in Houdini due to other limitations of Unreal.
*Edit - This gave me a good starting point on the issue that I am having. https://www.sidefx.com/forum/topic/77812/ [www.sidefx.com]
I basically have 3 different pieces of geometry that are pipes with varying length. They are copied to the points and overlap each other due to the different lengths. The end goal is to copy the different pipes, which are being copied using the @piecenum attribute and then have them fit together.
I have accomplished this in Unreal using Blueprints, this time it has to be completed in Houdini due to other limitations of Unreal.
*Edit - This gave me a good starting point on the issue that I am having. https://www.sidefx.com/forum/topic/77812/ [www.sidefx.com]
Edited by GlenD - 2023年2月15日 08:40:19
- GlenD
- Member
- 118 posts
- Joined: 12月 2013
- Offline
Working on a different part of this tool, with the unevenly distributed points along a curve. I have a pipes tool that I am creating and I would like to place different geometry with varying lengths along the spline. Similar to how a Spline Mesh tool places geometry in Unreal. The different pipes should be placed along the spline until the corner and then scale to appropriate length. I have solved the scale along spline using a Bend node -> Length and Scale. The corners have been solved as well. This is a tool that uses existing geometry and not procedural geometry.
The issue is the curve resample. The 'copy to points' node only copies on to the points based on a resample distance. I have rebuilt the curve points based on the length of the different geometry to little success.
It is the rebuilding of the curve that is the biggest block. Has anyone created a tool like this before?
The issue is the curve resample. The 'copy to points' node only copies on to the points based on a resample distance. I have rebuilt the curve points based on the length of the different geometry to little success.
It is the rebuilding of the curve that is the biggest block. Has anyone created a tool like this before?
- Digipiction
- Member
- 166 posts
- Joined: 3月 2014
- Offline
- Digipiction
- Member
- 166 posts
- Joined: 3月 2014
- Offline
Actually, this isn't entirely correct. Since it uses the primuv method as suggested above, the length of the resulting line segments will be off, potentially by a large amount.
As an example, let's say the first segment needed to go from point 16 to point 30 (sorry about the point numbers, I merged the splines into one geometry): primuv will calculate the length along that bend. But drawing a straight line from 16 to 30 will be considerably shorter than that.
This makes the problem trickier to solve, but I'm not sure if it's even a dealbraker as I don't think you considered that in the blueprints?
As an example, let's say the first segment needed to go from point 16 to point 30 (sorry about the point numbers, I merged the splines into one geometry): primuv will calculate the length along that bend. But drawing a straight line from 16 to 30 will be considerably shorter than that.
This makes the problem trickier to solve, but I'm not sure if it's even a dealbraker as I don't think you considered that in the blueprints?
- AlanZ
- Member
- 41 posts
- Joined: 2月 2018
- Offline
My 2 cents: I think your existing solution is the best possible one. Though I don't know how exactly are you creating new points from the last ones, and in what cases is this failing.
If I were doing this, I'd use a for-loop or a solver so that I can leverage the SOP nodes available instead of just using VEX. (This is too hard/costly to get right using a single VEX wrangler.) Inside the loop/solver, I'd either:
a. Create a circle/sphere primitive (center: last point, radius: desired segment length), find intersections to the curve using an intersection analysis node, and choose one of the intersections based on some rules (nearest? farthest? whatever). If no intersection, break.
or:
b. For each segment of the curve (assuming you've resampled the curve; use e.g. a point wrangle to deal with each segment), perform line-sphere intersection test with a conceptual circle/sphere (same as the one above) in VEX manually. Choose one with whatever method you like (e.g. attribute promote).
or:
c. Cut off the curve from the last point. Use a resample node again (even length segments, length = desired length, turn off `Even last segment same length`) to get the next point (pt1 of the resampled points). Discard the rest of the resampled points.
I don't know which one would be faster. And then again there might be some built-in nodes I just forgot.
If I were doing this, I'd use a for-loop or a solver so that I can leverage the SOP nodes available instead of just using VEX. (This is too hard/costly to get right using a single VEX wrangler.) Inside the loop/solver, I'd either:
a. Create a circle/sphere primitive (center: last point, radius: desired segment length), find intersections to the curve using an intersection analysis node, and choose one of the intersections based on some rules (nearest? farthest? whatever). If no intersection, break.
or:
b. For each segment of the curve (assuming you've resampled the curve; use e.g. a point wrangle to deal with each segment), perform line-sphere intersection test with a conceptual circle/sphere (same as the one above) in VEX manually. Choose one with whatever method you like (e.g. attribute promote).
or:
c. Cut off the curve from the last point. Use a resample node again (even length segments, length = desired length, turn off `Even last segment same length`) to get the next point (pt1 of the resampled points). Discard the rest of the resampled points.
I don't know which one would be faster. And then again there might be some built-in nodes I just forgot.
Edited by AlanZ - 2023年3月14日 14:08:35
- animatrix_
- Member
- 4638 posts
- Joined: 2月 2012
- Offline
You can do this easily with primuvconvert and primuv VEX functions. Just move the reference curve points over the curve you want to resample after you compute unit length U coordinates.
float n = float ( @ptnum ) / ( len ( primpoints ( 0, @primnum ) ) - 1 ); float u = primuvconvert ( 0, n, @primnum, 4 ); @P = primuv ( 1, "P", 0, u );
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
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]
youtube.com/@pragmaticvfx | patreon.com/animatrix | pragmaticvfx.gumroad.com
- AlanZ
- Member
- 41 posts
- Joined: 2月 2018
- Offline
I had the time to implement one of my ideas today. I'm not entirely sure if I understand you correctly, but if exact segment length is what you want (for copying rigid modular geometries), I believe my answers were necessary. As Digipiction pointed out, simply using
primuv
measures the curve by arc, not chord, giving you incorrect lengths. Among my three answers I chose option c because it seems to be the simplest to implement, but still it's ~15 nodes. I'd be happy to elaborate on it if I haven't misunderstood you and this is indeed what you meant. Please check my screenshots.
- mestela
- Member
- 1772 posts
- Joined: 5月 2006
- Offline
- GlenD
- Member
- 118 posts
- Joined: 12月 2013
- Offline
- GlenD
- Member
- 118 posts
- Joined: 12月 2013
- Offline
AlanZ
I had the time to implement one of my ideas today. I'm not entirely sure if I understand you correctly, but if exact segment length is what you want (for copying rigid modular geometries), I believe my answers were necessary. As Digipiction pointed out, simply usingprimuv
measures the curve by arc, not chord, giving you incorrect lengths. Among my three answers I chose option c because it seems to be the simplest to implement, but still it's ~15 nodes. I'd be happy to elaborate on it if I haven't misunderstood you and this is indeed what you meant. Please check my screenshots.
Hi AlanZ, This seems to be the closest setup that I am looking for. Could you elaborate a bit more on the setup or post a hip if possible? I would need exact segment lengths due to the rigid length of the geometry. Also, thanks for the assistance.
Glen
Edited by GlenD - 2023年3月16日 04:28:43
- GlenD
- Member
- 118 posts
- Joined: 12月 2013
- Offline
mestelaHi Matt, thanks for the information on those nodes, I didn't know they existed. I tried them both out, and they get me close to what I need just not close enough. I am currently testing it with a tube that is 1 unit, 3 units and 5 units in length.
There's also the labs progressive resample and labs resample by density sops, handy.
When I input the resolution scale to either 1, 3 or 5 it will always match 2 of 3 unit lengths. One of them is always off in length. I may be missing something at the moment or it may just a limitation. I may just have to only have two different unit lengths of geometry.
Glen
- AlanZ
- Member
- 41 posts
- Joined: 2月 2018
- Offline
- tamte
- Member
- 8749 posts
- Joined: 7月 2007
- Offline
- AlanZ
- Member
- 41 posts
- Joined: 2月 2018
- Offline
- GlenD
- Member
- 118 posts
- Joined: 12月 2013
- Offline
Thank you everyone for the assistance. The resample section is part of a larger tool that uses existing geometry and places it along a spline. The art department creates the pipes that will be eventually used for this tool. In the image below, it goes through the various steps of creating the resample section. We tried using the 'Curve Solver' and it didn't translate well to Unreal. It could also be a step we are missing too.
The orange box copies various geometry on the points using this setup. https://www.sidefx.com/docs/houdini/copy/copytopoints.html [www.sidefx.com]
The green box network takes each pipe that is created and calculates the length of the pipe. This is only 1 or 3 since our pipes are a set length. The pink colored nodes is a Sort node that sorts the point order 'Along Vector' using the curve direction 'N'. the only points that are left is a start point of each pipe length.
The purple box creates a 'point array' from the pipe lengths and then a sum of those lengths. This is used to create the distance between the points.
The blue box recalculates the primitives that the points will be applied. All this data is calculated in the 'create_points_based_on_geometry_length'.
Since the length of the original primitive is either shorter or longer than the pipes that are recopied onto the points. A 'bend' node using 'Length Scale' and setting a 'Capture Origin' and 'Capture Direction' at the beginning of each primitive spline. This happens at another point in the tool and is not shown in the image below.
Overall, it is fast, responsive and it enables the Level Artists to dress scenes quickly. On and off it took a little over a month to finish the tool. Requirements were to create a tool that takes existing geometry and place it along a spline.
The 'Corner Pipes' also use existing geometry and the bend is calculated with a Bend deformer, which is calculated in a different branch. The 'Capture Direction' is calculated based on an angle between the current point, previous point, and next point. Which is then calculated by Projecting the V on U. https://gamedev.stackexchange.com/questions/70252/how-can-i-project-a-vector-on-another-vector [gamedev.stackexchange.com]
Procedural geometry doesn't optimise well in Unreal, this is why we went with this approach. Once I clean up the network, and get approval I will post up the hip file.
The orange box copies various geometry on the points using this setup. https://www.sidefx.com/docs/houdini/copy/copytopoints.html [www.sidefx.com]
The green box network takes each pipe that is created and calculates the length of the pipe. This is only 1 or 3 since our pipes are a set length. The pink colored nodes is a Sort node that sorts the point order 'Along Vector' using the curve direction 'N'. the only points that are left is a start point of each pipe length.
The purple box creates a 'point array' from the pipe lengths and then a sum of those lengths. This is used to create the distance between the points.
The blue box recalculates the primitives that the points will be applied. All this data is calculated in the 'create_points_based_on_geometry_length'.
Since the length of the original primitive is either shorter or longer than the pipes that are recopied onto the points. A 'bend' node using 'Length Scale' and setting a 'Capture Origin' and 'Capture Direction' at the beginning of each primitive spline. This happens at another point in the tool and is not shown in the image below.
Overall, it is fast, responsive and it enables the Level Artists to dress scenes quickly. On and off it took a little over a month to finish the tool. Requirements were to create a tool that takes existing geometry and place it along a spline.
The 'Corner Pipes' also use existing geometry and the bend is calculated with a Bend deformer, which is calculated in a different branch. The 'Capture Direction' is calculated based on an angle between the current point, previous point, and next point. Which is then calculated by Projecting the V on U. https://gamedev.stackexchange.com/questions/70252/how-can-i-project-a-vector-on-another-vector [gamedev.stackexchange.com]
Procedural geometry doesn't optimise well in Unreal, this is why we went with this approach. Once I clean up the network, and get approval I will post up the hip file.
Edited by GlenD - 2023年3月28日 03:50:36
- BabaJ
- Member
- 2114 posts
- Joined: 9月 2015
- Offline
You can do this easily with primuvconvert and primuv VEX functions.
Thanks Animatrix for the reference of primuvconvert. It was what I was needing as I had a similar 'issue' I needed to solve that was similar to this thread I was aware of.
I was attempting to plot points on a curve(non-polylines) that were not to be a part of the curve itself - just along 'on' the curve position wise.
I thought primuv would do the trick in giving a 'fit' of 'distance' along the curve to the u of 0-1. e.g. assumed a u of 0.2 would plot my point at 2 for say a curve 10 units in length.
However primuv function doesn't give such proportional result, unless of course the bezier/nurbs curve is only of an order of 2, or the line itself is only a polyline - in which primuv works as desired.
But the primuvconvert with the 'mode' argument set to PRIMUV_UNITLEN_TO_LEN does give the 'proportional' distance to u coordinates along a bezier/nurbs curve with orders greater than 2.
Thanks again for your post.
Edited by BabaJ - 2023年3月30日 13:30:58
-
- Quick Links