- Home /
Perpendicular to a 3D direction vector
Hello.
I'm trying to figure out how to create a vector that is perpendicular to a 3D direction vector that is to the left or right of the source position.
If you look at the image below, I have two position vectors, A and B. Getting the direction and delta angle between those two is simple enough, but I'm trying to get a Perp vector from B that is 90 degrees from the direction between the two (the magenta line in the illustration), as well, the direction of that perp vector is either left or right depending on whether or not the delta angle is positive or negative.
This is really just a 2D calculation (X/Z) because Y will always be zero, but I am working in 3D if it makes a difference.
I've tried looking at Vector3.Project() and looking at other posts that calculate Normals but I'm clearly not doing something correctly. If anyone has a solution to this they're willing to share I would appreciate it.
thanks.
Answer by Bunny83 · Mar 31, 2017 at 05:44 PM
Simply do:
Vector3 dir = B-A;
Vector3 left = Vector3.Cross(dir, Vector3.up).normalized;
//Vector3 right = -left;
//Vector3 right = Vector3.Cross(Vector3.up, dir).normalized;
//Vector3 right = Vector3.Cross(-dir, Vector3.up).normalized;
//Vector3 right = Vector3.Cross(dir, -Vector3.up).normalized;
All the commented out examples will give you the opposite direction to the right. Since Unity uses a left-handed-system you have to use the "left-hand-rule" (Cross(Thumb, index finger) == middle finger). Make sure your thumb and index finger form an "L" and the middle finger is perpendicular to the other two.
Also note that the "length" of the cross product is the area of the parallelogram defined by the two given vectors. Since we only search a direction the length usually doesn't matter. So you usually want to normalize the result.
Keep in mind if the two given vectors of a cross product point in the same or exact opposite direction the result will be (0,0,0)
edit
In 2d it's way simpler to get a vector that is 90° to a given direction. Just swap the two components (X and Z) and invert one of them. Which one you invert defines if you rotate clockwise or counter-clockwise.
// clockwise
Vector3 Rotate90CW(Vector3 aDir)
{
return new Vector3(aDir.z, 0, -aDir.x);
}
// counter clockwise
Vector3 Rotate90CCW(Vector3 aDir)
{
return new Vector3(-aDir.z, 0, aDir.x);
}
So a direction that is 90 rotated could be calculated like this:
Vector3 left = Rotate90CCW(B-A).normalized;
Vector3 right = Rotate90CW(B-A).normalized;
Thank you!.. yes, the second suggestion worked just fine. I couldn't for the life of me get the cross product to work, so the rotation of the direction worked as expected.
//Get the direction and give it a magnitude that is the same as our distance.
Vector3 Direction = (_TargetPosition - _PlayerPosition);
Vector3 NewTarget = _TargetPosition + Util.RotateVector90(Direction, false);
public static Vector3 RotateVector90(Vector3 aDir, bool _ClockWise)
{
if(_ClockWise)
return new Vector3(aDir.z, 0, -aDir.x);
else
return new Vector3(-aDir.z, 0, aDir.x);
}
thank you for your help, this solved a problem I've been working on for a while now.
I'm not sure how to mark yours as the answer as there doesn't seem to be a button to do that.
Well, i originally posted just a comment since @Nose$$anonymous$$ills already answered the question. However since my comment has "grown" i just converted it into an answer ^^.
ps: This "swapping rule" can be directly derived from the cross product. Inside the x-z plane the up vector is (0,1,0) and the input direction vector is always (x,0,z). Those "0"s simply strip away most terms of the cross product so only the two input components remain.
R = U x V --> (0, 1, 0) x (Vx, 0, Vz)
-->
Rx = Uy * Vz - Uz * Vy
Ry = Uz * Vx - Ux * Vz
Rz = Ux * Vy - Uy * Vx
Rx = 1 * Vz - 0 * 0 --> Vz
Ry = 0 * Vx - 0 * Vz --> 0
Rz = 0 * 0 - 1 * Vx --> -Vx
Answer by NoseKills · Mar 31, 2017 at 04:22 PM
A single 3D vector has an infinite amount of vectors perpendicular to it. Vector3.up for example is perpendicular to any non-zero vector that has y == 0.
Besides that technicality, what you are looking for is cross product.
Vector3.Cross (a, b);
returns a vector that is perpendicular to the plane defined by vectors a and b, as long as they define a plane (they are not collinear)
Looking at your image, you want the cross product between vectors AB and Vector3.up (if the y-coordinate of both points are guaranteed to be the same), but i guess the image can be misleading... If A and B can be anything, without limitations or rules, you need to provide more information about the situation so we can determine which b vector to use in our cross product. Otherwise the magenta vector can be rotated around axis AB and it'll always be perpendicular to it.
B vector can be any position relative to the A position, except above or below it. The Y's are always the same (zero). This is a 3D game, but chracters only move on a 2D plane (X,Z). So I guess that's safe to say it's guaranteed.
I tried Vector3.cross() but my XZ is co$$anonymous$$g up as 0 but my Y value is huge, so I must not be including the vector3.up in the correct location.
thanks
Your answer
Follow this Question
Related Questions
"Fake" Vector3.forward? 3 Answers
How to rotate an object to face the direction it's going? 1 Answer
how to get a perpendicular vector for wall-jumping 2 Answers
Transform angle to grid position 2 Answers
Make a moving object continue it's movement from the same direction , even it reaches target 1 Answer