VEX - Calculating perpendicular vector to given direction

   1387   18   2
User Avatar
Member
90 posts
Joined: 10月 2021
Offline
Hey there,

I am trying to calculate the perpendicular vector to a dynamic direction in vex but so far I just cant get it to work. Cross product came to mind but then I would need two vectors to calculate the perpendicular, but in this case I just have one direction from pt0 to pt1.


Edited by Kareeem - 2025年2月28日 08:05:39

Attachments:
sample.png (273.7 KB)

www.rehimi.de
User Avatar
Member
500 posts
Joined: 11月 2016
Offline
There is an infinity of vectors perpendicular to your direction. Cross product is indeed what you need. If any perpendicular vector will do, just use any vector as the second argument of your cross product. If you need a specific one, try to figure out on which plane you want it to be and use the normal of that plane as your second cross product vector.

This [en.wikipedia.org] might be of help.
Edited by Tanto - 2025年2月28日 10:00:56
User Avatar
Member
4853 posts
Joined: 2月 2012
Online
Hi,

You can do it like this:

vector getPerpendicularVector ( vector v )
{
    vector vn = normalize ( v );
    vector vu = abs ( vn.x ) < abs ( vn.z ) ? { 1, 0, 0 } : { 0, 0, 1 };

    return normalize ( cross ( vn, vu ) );
}
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com] https://lnk.bio/animatrix [lnk.bio]
User Avatar
Member
243 posts
Joined: 5月 2017
Offline
This should also work
vector n = normalize(set(p.z, 0, -p.x));
addpoint(0, p + n);
User Avatar
Member
90 posts
Joined: 10月 2021
Offline
animatrix_
Hi,

You can do it like this:

vector getPerpendicularVector ( vector v )
{
    vector vn = normalize ( v );
    vector vu = abs ( vn.x ) < abs ( vn.z ) ? { 1, 0, 0 } : { 0, 0, 1 };

    return normalize ( cross ( vn, vu ) );
}

Wow, this seems advanced. I am having trouble understanding even the first line. What is this syntax? A short version for something?
Thanks for taking the time though, much appreciated!
www.rehimi.de
User Avatar
Member
90 posts
Joined: 10月 2021
Offline
vikus
This should also work
vector n = normalize(set(p.z, 0, -p.x));
addpoint(0, p + n);

This actually works, thanks! I needed to fix it up a bit though

vector n = normalize(set(@P.z, 0, -@P.x));
addpoint(0, @P + n);

I´ll try to figure out what you are doing here ... I mean I get what you are doing but how on earth would one think of that?
Edited by Kareeem - 2025年2月28日 10:27:05
www.rehimi.de
User Avatar
Member
243 posts
Joined: 5月 2017
Offline
It normal of a 2D vector. Fliping the axis of P and negate one of them. Hope the image explains .

Works in 3D as well you can build stable rotaion on that.

Attachments:
2DVectorNormal.jpg (14.1 KB)

User Avatar
Member
90 posts
Joined: 10月 2021
Offline
vikus
It normal of a 2D vector. Fliping the axis of P and negate one of them. Hope the image explains .
Image Not Found

Works in 3D as well you can build stable rotaion on that.

It explains that I should have smoked less weed in school. Thanks that definitely makes more sense now!
www.rehimi.de
User Avatar
Member
243 posts
Joined: 5月 2017
Offline
Kareeem
Thanks that definitely makes more sense now!
Glad to help.

Here is an older file with rotation, scale where I lern the stuff:
Image Not Found

Attachments:
Vector_Normal.hiplc (141.3 KB)

User Avatar
Member
90 posts
Joined: 10月 2021
Offline
vikus
Kareeem
Thanks that definitely makes more sense now!
Glad to help.

Here is an older file with rotation, scale where I lern the stuff:
Image Not Found

Great, I will check that out!
www.rehimi.de
User Avatar
Member
9121 posts
Joined: 7月 2007
Offline
Kareeem
This actually works, thanks! I needed to fix it up a bit though
vector n = normalize(set(@P.z, 0, -@P.x));
I´ll try to figure out what you are doing here ... I mean I get what you are doing but how on earth would one think of that?
you can also write the same thing as :
vector n = normalize( cross( @P, {0,-1,0} ) );
but once you expand the math of the cross product that's what's left
Edited by tamte - 2025年2月28日 12:12:16
Tomas Slancik
CG Supervisor
Framestore, NY
User Avatar
Member
90 posts
Joined: 10月 2021
Offline
tamte
Kareeem
This actually works, thanks! I needed to fix it up a bit though
vector n = normalize(set(@P.z, 0, -@P.x));
I´ll try to figure out what you are doing here ... I mean I get what you are doing but how on earth would one think of that?
you can also write the same thing as :
vector n = normalize( cross( @P, {0,-1,0} ) );
but once you expand the math of the cross product that's what's left


Oh wow, i think I finally got it now. I thought for some reason that the two vectors I feed into the cross product need to be perpendicular to each other to beginn with and if they are not the result of the cross product would also not be perpendicular.

I think this image gave me that idea

Attachments:
cross.png (167.2 KB)

www.rehimi.de
User Avatar
Member
90 posts
Joined: 10月 2021
Offline
Tanto
There is an infinity of vectors perpendicular to your direction. Cross product is indeed what you need. If any perpendicular vector will do, just use any vector as the second argument of your cross product. If you need a specific one, try to figure out on which plane you want it to be and use the normal of that plane as your second cross product vector.

This [en.wikipedia.org] might be of help.



So you were correct right from the start. I can use any vector as the 2nd argument. How cool is that cross function?!
Edited by Kareeem - 2025年2月28日 14:38:03
www.rehimi.de
User Avatar
Member
4853 posts
Joined: 2月 2012
Online
Kareeem
animatrix_
Hi,

You can do it like this:

vector getPerpendicularVector ( vector v )
{
    vector vn = normalize ( v );
    vector vu = abs ( vn.x ) < abs ( vn.z ) ? { 1, 0, 0 } : { 0, 0, 1 };

    return normalize ( cross ( vn, vu ) );
}

Wow, this seems advanced. I am having trouble understanding even the first line. What is this syntax? A short version for something?
Thanks for taking the time though, much appreciated!

It's ternary operator [en.m.wikipedia.org].
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com] https://lnk.bio/animatrix [lnk.bio]
User Avatar
Member
90 posts
Joined: 10月 2021
Offline
animatrix_
It's ternary operator [en.m.wikipedia.org].


Hey thanks for clarifying! Although I did not know that term I was aware of the"short version" of the if statement.
But I am still not sure what you are doing in the first line ... Are you creating a custom function here?
Edited by Kareeem - 2025年3月1日 02:40:13
www.rehimi.de
User Avatar
Member
4853 posts
Joined: 2月 2012
Online
Kareeem
animatrix_
It's ternary operator [en.m.wikipedia.org].


Hey thanks for clarifying! Although I did not know that term I was aware of the"short version" of the if statement.
But I am still not sure what you are doing in the first line ... Are you creating a custom function here?

Yes.
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com] https://lnk.bio/animatrix [lnk.bio]
User Avatar
Member
90 posts
Joined: 10月 2021
Offline
animatrix_
Hi,

You can do it like this:

vector getPerpendicularVector ( vector v )
{
    vector vn = normalize ( v );
    vector vu = abs ( vn.x ) < abs ( vn.z ) ? { 1, 0, 0 } : { 0, 0, 1 };

    return normalize ( cross ( vn, vu ) );
}

I dissected this and wrote it down in vex code I can understand for a detail wrangle and without the custom function. Thank you for the inspiration. I still have a hard time understanding how you can come up with the math but I guess it again comes down to the basic knowledge Vicus posted here as well and experience.

// calc dir from start to end
vector start = point(0, "P", 0);
vector end = point(0, "P", 1);
vector dirn = normalize(end-start);
vector diru;


// calc math magic
if (abs(dirn.x) < abs(dirn.z)) {
    diru = {1,0,0};
}
else{
    diru = {0,0,1};
}

// export @
v@N = normalize(cross(dirn, diru));
Edited by Kareeem - 2025年3月1日 07:57:49
www.rehimi.de
User Avatar
Member
4853 posts
Joined: 2月 2012
Online
The abs line picks the axis that is least aligned with vn, ensuring the cross product produces a well-conditioned perpendicular vector with a stable magnitude.

If vn is already close to { 1, 0, 0 } (X-axis), then { 1, 0, 0 } is a bad choice for vu because the cross product would produce a very small (almost zero) vector, leading to numerical issues.

If vn is closer to { 0, 0, 1 } (Z-axis), then { 0, 0, 1 } is a bad choice for the same reason.
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com] https://lnk.bio/animatrix [lnk.bio]
User Avatar
Member
90 posts
Joined: 10月 2021
Offline
animatrix_
The abs line picks the axis that is least aligned with vn, ensuring the cross product produces a well-conditioned perpendicular vector with a stable magnitude.

If vn is already close to { 1, 0, 0 } (X-axis), then { 1, 0, 0 } is a bad choice for vu because the cross product would produce a very small (almost zero) vector, leading to numerical issues.

If vn is closer to { 0, 0, 1 } (Z-axis), then { 0, 0, 1 } is a bad choice for the same reason.

Nice, thanks for explaining it once again!
www.rehimi.de
  • Quick Links