Jump to content

Average Tangents


galagast

Recommended Posts

I have a curve with a polyFrame SOP set to create tangentv (yellow).

avg_tangents_1.jpg

But I was hoping that the vectors were averaged (except for the first and last points).
So far, I was able to wrangle something, which currently works for what I want (green).

avg_tangents_2.jpg

I was just wondering if there was a simpler method (just for learning purposes)? Any insights would be very helpful. Thanks! ^_^

 

 

avg_tangents_v1.hiplc

Link to comment
Share on other sites

Hey Marty, thanks for the reply. I did try those before.. but I noticed that it is missing some sort of normalization.

As an example, if the "Two Edges" are of equal length, I get the desired result:
avg_tangents_v2_1.jpg
But if they are not equal:
avg_tangents_v2_2.jpg
The tangent leans more towards the longest edge.

It would be great if the PolyFrame SOP maybe had a checkbox that would normalize the edges.
I guess I could try and send an RFE a bit later after getting/hearing more feedback regarding this topic :-)

Houdini Indie H15.5.673

 

avg_tangents_v2.hiplc

Edited by galagast
Link to comment
Share on other sites

or you can do it using your own Polyframe implementation:

 

or the wrangle conversion I made of that (runs in primitive mode):

float displace = ch("displace");
int closed = primintrinsic(0,"closed",@primnum);

for(int i=0;i<@numvtx;i++)
{
    int pt = vertexpoint(0,vertexindex(0,@primnum,i));
    int pt0 = vertexpoint(0,vertexindex(0,@primnum,(i+1)%@numvtx));
    int pt1 = vertexpoint(0,vertexindex(0,@primnum,(i-1)%@numvtx));

    vector ptP = point(0,"P",pt);
    vector pt0P = point(0,"P",pt0);
    vector pt1P = point(0,"P",pt1);

    vector dir0 = normalize(pt0P-ptP);
    vector dir1 = normalize(ptP-pt1P);

    vector up = normalize(cross(dir0,-dir1));
    vector avDir = normalize(dir0+dir1);

    if(!closed)
    {
        if(i==0)
            avDir = dir0;
        if(i==@numvtx-1)
        {
            avDir = -dir1;
            dir0 = dir1;
        }
    }
    
    float dot = dot(dir0,avDir);
    vector tangent = normalize(cross({0,1,0},avDir))/dot;
    setpointattrib(0,"P",pt,ptP+tangent*displace,"set");
}

if you just want the tangent replace the last 3 lines with (ofcourse), depending of your H version you may need to pregenerate a N attribute:

    setpointattrib(0,"N",pt,normalize(cross({0,1,0},avDir))/dot);
}

 

Edited by acey195
  • Like 4
Link to comment
Share on other sites

Awesome Twan! These are great! Thank you so much :)

I love that you added handling of open and closed curves.

I also just realized that by doing that in primitive mode, you also covered handling of multiple line primitives! Cool!

Lastly, on my earlier attempts, I was scratching my head trying to figure out why upon displacing the points, their distances seems to vary.. After looking at your vex code, I noticed that i just had to divide the tangent by the the dot product! >__<

Edited by galagast
learned a lot!
Link to comment
Share on other sites

@acey195: A small question regarding your code.. you created an up vector (in line 17), but did not use it elsewhere.

I tried replacing line 32 from this:

vector tangent = normalize(cross({0,1,0},avDir))/dot;

to this:

vector tangent = normalize(cross(up,avDir))/dot;

But it seems it is not the way to go, as some displacements were flipped.

 

I also tried to compare it against the result of a polyExtrude (with the same amount of displacement/extrusion):

wrangle_tangent.jpg

It is just a minor thing, it got me curious how polyExtrude does its tangent calculation. :D

Link to comment
Share on other sites

If you have shape that is not aligned with the XZ plane, you could use the custom up vector,
but then it does become important in which direction the curve is drawn.
Or maybe I just put the cross product arguments in the wrong order.

About the difference with the polyextrude... I have no idea :P

Link to comment
Share on other sites

Haha no worries man, I'll just play around this a bit more. I have already learned quite a lot from it. Thank you again :D

 

EDIT:

Setting the up vector to absolute seems to have fixed the flipping. (at line 17)

vector up = abs(normalize(cross(dir0,-dir1)));

I like that it produces a more sensible result in that the tangents are properly oriented, but it still does not match polyExtrude's version. Using a constant {0,1,0} for up is still a much closer match.

Edited by galagast
found fix for flipping
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...