How can I compute a proper tangent vector field?

   2356   5   3
User Avatar
Member
355 posts
Joined: 11月 2015
Offline
Hi guys/ladies, how can I compute a proper vector field that's tangent to any arbitrary mesh in VEX? I used the polyframe SOP but there are some inconsistencies with the vector directions and plus I'd love to know a VEX approach for creating a proper tangent field on arbitrary mesh. Thanks in advance. (I've provided a file with the mesh I'm currently working on; see attached)

Attachments:
compute_tangent_field_HELP_01.hip (3.1 MB)

hou.f*ckatdskmaya().forever()
User Avatar
Member
4516 posts
Joined: 2月 2012
Offline
Hi,

One way to obtain such a field would be by using contour lines:



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
355 posts
Joined: 11月 2015
Offline
@animatrix_ thanks a lot, I'll dive into this material and the course really is some next level shit! I'm very interested and will definitely be looking to purchase that. I'm super interested in learning these advanced math concepts in the context of VEX and Houdini.
Edited by traileverse - 2021年8月23日 01:15:45
hou.f*ckatdskmaya().forever()
User Avatar
Member
355 posts
Joined: 11月 2015
Offline
@animatrix_ one question, is there an attribute I could create to take the gradient of that would give tangent vector flowing in a direction that conforms the mesh edges flow?
hou.f*ckatdskmaya().forever()
User Avatar
Member
4516 posts
Joined: 2月 2012
Offline
In the above code it doesn't create a tangent attribute but you can either store the grad attribute (blue) in the same wrangle or compute it afterwards using Orientation along Curve or PolyFrame SOP to create a tangent field.

string costattrib = chs("costattrib");
string directionattrib = chs("directionattrib");
int usecost = chi("usecost");
float stepsize = ch("stepsize");
float stepsizemultiplier = ch("stepsizemultiplier");
float mindist = ch("mindist");
float maxdist = ch("maxdist");

float dist = stepsize;
float tolerance = 0.0001;

vector pos [ ] = { };
float dists [ ] = { };
vector grads [ ] = { };
vector normals [ ] = { };

int hitpr = -1;
vector hituv = 0;

vector p = @P;
xyzdist ( 1, p, hitpr, hituv );
p = primuv ( 1, "P", hitpr, hituv );
vector grad = primuv ( 1, directionattrib, hitpr, hituv );
vector normal = primuv ( 1, "N", hitpr, hituv );
float cost = primuv ( 1, costattrib, hitpr, hituv );
float lastcost = cost;

append ( pos, p );
append ( dists, 0 );
append ( grads, grad );
append ( normals, normal );

float sumdist = 0;
while ( sumdist <= maxdist )
{
    p += normalize ( grad ) * stepsize;
    xyzdist ( 1, p, hitpr, hituv );
    p = primuv ( 1, "P", hitpr, hituv );
    grad = primuv ( 1, directionattrib, hitpr, hituv );
    normal = primuv ( 1, "N", hitpr, hituv );
    cost = primuv ( 1, costattrib, hitpr, hituv );
    
    if ( usecost && cost >= lastcost - tolerance )
    {
        stepsize *= stepsizemultiplier;
        if ( abs ( stepsize ) < tolerance )
            break;
    }
    else
    {
        dist = distance ( pos [ -1 ], p );
        if ( dist < tolerance )
            break;
        
        sumdist += dist;
        append ( pos, p );
        append ( dists, sumdist );
        append ( grads, grad );
        append ( normals, normal );
        
        lastcost = cost;
    }
}

if ( sumdist >= mindist )
{
    float m = 1.0 / sumdist;
    int count = len ( pos );
    int pts [ ] = { };
    for ( int i = 0; i < count; ++i )
    {
        int pt = addpoint ( 0, pos [ i ] );
        float s = dists [ i ] * m;
        vector color = chramp("color", s);
        
        vector grad = grads [ i ];
        vector normal = normals [ i ];
        vector bitangent = cross ( normal, grad );
        
        setpointattrib ( 0, "Cd", pt, color );
        setpointattrib ( 0, "grad", pt, grad );
        setpointattrib ( 0, "normal", pt, normal );
        setpointattrib ( 0, "bitangent", pt, bitangent );
        
        append ( pts, pt );
    }
    addprim ( 0, "polyline", pts );
}

removepoint ( 0, @ptnum );

If you want the vector field orthogonal to this, then you can either sample surface normals and compute the cross product between this and the grad (tangent) attribute and store the result (bitangent: green), or you can just use gradient ascent/descent and use the grad attribute which would be bitangent to the contour lines:



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
355 posts
Joined: 11月 2015
Offline
Thanks @animatrix_ this was super helpful! I ended up doing a little hacking of the LABS straight skeleton 3D SOP (which in itself is a really cool way of using VDB to generate center curves for a mesh) and transferred the normals(normals that are tangent to the curve) to the mesh using a nearpoint lookup (file attached).

Attachments:
compute_tangent_field_HELP_02.hip (3.4 MB)

hou.f*ckatdskmaya().forever()
  • Quick Links