# Angle Between Two Vectors In 3d

9 replies to this topic

### #1 1101

1101

GMC Member

• GMC Member
• 462 posts

Posted 07 May 2010 - 07:09 AM

Alright so I have a camera that uses rotation about an arbitrary axis to rotate in any which way without gimbal lock. I would like to find the angle between the camera's current up vector (which can be any unit vector) to the vector <0,0,-1>. The method I'm currently using is to take the arccos of the dot product of the camera's up vector and <0,0,-1> which sorta works. The problem is that using arccos is presenting two problems.

1) arccos range is only from 0 to pi so I cannot distinguish between 90 and -90 degrees of rotation (which I would like to be represented as 90 and 270 degrees respectively).

2) arccos is apparently undefined at some points. I'm getting error notices for arccos as I'm rotating around. What I'm thinking is that this is because the camera's up vector may not a perfect unit vector (ie its <0,1.001,0> or something like that).

Anyways I would like to know if there's a way to find the angle of rotation between two vectors in 3d space without using an arccos function or any other method that would experience similar problems.

I think this site

http://www.euclidean...tween/index.htm

is presenting some sort of alternative dealing with quaterions and matrices but I do not understand it very well.

Edited by 1101, 07 May 2010 - 07:10 AM.

• 0

### #2 sabriath

sabriath

12013

• GMC Member
• 3197 posts

Posted 07 May 2010 - 07:23 AM

You do realize that angle difference is UP TO 180 degrees right? It doesn't matter if it's 2d, 3d or even 328d, if you have 2 vectors, then the angle between those vectors cannot be more than a line (180 degrees)....this is why you get an answer from 0 to pi. I think your question is how to detect the angles direction of rotation given an origin vector.

For example, given a 2d vector of {0,1} and {1,0} is a difference of 90 degrees (a right angle), but if we say that {0,1} is the origin vector, then to reach {1,0} would be -90 degrees direction. In 3d it's the same thing, {0,0,1} and {1,1,0} would be an angle difference of 90 degrees (still a right angle but at a diagonal to the x/y axis), and if we say that the origin is {0,0,1}, then to reach {1,1,0} from there would be {-90xz, -90yz, 0xy}....unless you use polar notation for the angle changes.

For the equation though, I don't have it handy and I'm too tired to figure it out by hand right now. good luck.
• 0

Tutorials of Interest:
* Multiplayer: mine or True Valhalla's

Projects:
* Net39
* My 39dll scripts
* My 39dll lib
* Multiplayer Engine
* Artificial Chemistry

### #3 Tepi

Tepi

GMC Member

• Global Moderators
• 4248 posts
• Version:GM:Studio

Posted 07 May 2010 - 10:48 AM

See my post here. It explains how to find the shortest route from one direction to another and figures out the angle and rotation axis based on that. Exactly what you want, if I understood correctly.

P.s. If you're not sure if the up-vector is normalized, normalize it. It will produce some really weird results otherwise.
• 0

### #4 1101

1101

GMC Member

• GMC Member
• 462 posts

Posted 07 May 2010 - 09:10 PM

Ok the problem is I don't want the shortest angle between two vectors. I want the directional angle (if that term really exists). I only want to concern myself with counter-clockwise rotation. So a rotation of negative 90 degrees would be calculated as a rotation as positive 270 degrees.

Tepi I am using the exact formula you have given me. The point to rotate around is (0,0,0) so it has no effect on the equation. The original vector is <0,0,1> and the new vector is a unit vector of any value <x,y,z>. In this way their magnitudes are the same and are equal to 1 (so the denominator in the equation also has no effect). Further since the original vector is always <0,0,1> the only thing that the arccos takes is the z component of the new vector.

so essentially I'm left with: angle = arccos(z_component_of_B)*180/pi,
the 180/pi being used to convert radians to degrees

And yes you are right the up vector should have been normalized to <0,0,1> (but the problem still persists).

EDIT:

which states that this problem can be solved in 2 dimensions using the equation angle = atan2(norm(cross(a,b)),dot(a,b)). I don't suppose there's a similar method for three dimensions?

Edited by 1101, 07 May 2010 - 09:38 PM.

• 0

### #5 Gamer3D

Gamer3D

Human* me = this;

• GMC Member
• 1819 posts
• Version:GM:Studio

Posted 07 May 2010 - 10:48 PM

Your problem is that counter-clockwise from one side is clockwise from the other. Things you CAN find are:

Angle between vectors (This is the smallest angle. Find it by taking the arccos of the dot product of two unit vectors)
Axis of rotation (This is the cross product of the two vectors. For our purposes, the magnitudes of the vectors and cross product are unimportant)

You can use the axis of rotation to figure out if it is clockwise rotation FROM A SPECIFIC POINT OF VIEW by taking the dot product of the axis and the view vector and checking its sign.
• 0
Fast Priority Queues - Game Maker's priority queues are O(n). Mine do everything that Game Maker's do, but in O(log n) time.
Dual-Quaternion Skinning - Modifying vertexes in GM is slow. This simple vertex shader does the job both quickly and well.

### #6 1101

1101

GMC Member

• GMC Member
• 462 posts

Posted 07 May 2010 - 11:02 PM

so basically I ended up using the same formula but added 180 to it and made one of the arguments negative

angle = 180 + (arctan2( N * ( V1 x V2 ), -(V1 * V2)))*180/pi

and that seems to work.

Though I'm not sure if I completely trust arctan2, it hasn't crashed yet but you never know...

Edited by 1101, 07 May 2010 - 11:05 PM.

• 0

### #7 Tepi

Tepi

GMC Member

• Global Moderators
• 4248 posts
• Version:GM:Studio

Posted 07 May 2010 - 11:15 PM

Tepi I am using the exact formula you have given me. The point to rotate around is (0,0,0) so it has no effect on the equation. The original vector is <0,0,1> and the new vector is a unit vector of any value <x,y,z>. In this way their magnitudes are the same and are equal to 1 (so the denominator in the equation also has no effect). Further since the original vector is always <0,0,1> the only thing that the arccos takes is the z component of the new vector.

so essentially I'm left with: angle = arccos(z_component_of_B)*180/pi,
the 180/pi being used to convert radians to degrees

What do you think is wrong with it? The axis of rotation* is (0,0,1) x (x,y,z) = (-y,x,0), which is perpendicular to the vector (x,y,0), which is the projection of (x,y,z) on x-y-plane. Now if you visualize this situation you will come to the same conclusion: in this case the angle depends only on the z-coordinate of the second vector.

*This is flipped version of the one in the post.

The formula you found from the internet is unnecessarily complicated. You can find the angle by the use of a single dot-product and the sign of the angle will come to effect as the calculated axis of rotation will flip around with it. What you found there did not even specify the axis of rotation so it's virtually useless. I don't really understand what you're not satisfied with in my solution. It works perfectly and I even told the singularities so that you wouldn't need to figure them out.
• 0

### #8 1101

1101

GMC Member

• GMC Member
• 462 posts

Posted 07 May 2010 - 11:30 PM

@Tepi

I do not know what you mean when you said "the sign of the angle will come to effect as the calculated axis of rotation will flip around with it" and "I even told the singularities so that you wouldn't need to figure them out". How do I find the sign of the angle? What do you mean the calculated axis of rotation will flip around? What does singularity mean in that context?

Your method is simpler but it doesn't distinguish between negative and positive rotation. Yes I realize that positive and negative rotation is relative and I have to use an axis of rotation to make this distinction. The method I found online refers to this axis as the normal and this is included in the equation so an axis is specified. I'd like to use your method but I cannot figure out how to make any distinction between positive and negative rotation.

I should also mention that for whatever reasons the use of an arcccos function causes sporadic errors, and the arctan2 function has not yet

EDIT:

I think I got your method to work. But it's giving the exact same results as the arctan2 method. I'm thinking they might be mathematically equivalent somehow (either in general or under the conditions i'm using). I'm guessing arccos is faster than arctan2. But arctan2 isn't crashing, so idk.

Edited by 1101, 07 May 2010 - 11:45 PM.

• 0

### #9 Tepi

Tepi

GMC Member

• Global Moderators
• 4248 posts
• Version:GM:Studio

Posted 07 May 2010 - 11:56 PM

@Tepi

I do not know what you mean when you said "the sign of the angle will come to effect as the calculated axis of rotation will flip around with it" and "I even told the singularities so that you wouldn't need to figure them out". How do I find the sign of the angle? What do you mean the calculated axis of rotation will flip around? What does singularity mean in that context?

Well the cross-product will flip from one side to the other whenever the vectors pass through each other. The direction of the cross-product can be visualized with the right-hand-rule. With this example, you should be able to visualize what happens when your fingers cross. This is the axis of rotation, which, when flipped, flips the direction of rotation. The shortest angle between vectors is never signed, so using their cross-product as the axis of rotation with this angle, you will always get the rotation you're looking for.

Now the singularities are the angles for which the calculations won't apply. These are explained in the post: when the axis of rotation becomes a null vector, the rotation can't be determined. In these cases (x,y,z) == (0,0,1) or (x,y,z) == (0,0,-1).

The problems with arccos might be because of precision errors (you have normalized the vectors, right?). I've experienced some problems with it in gm8 while everything had worked fine in the previous versions.
• 0

### #10 sub

sub

EVIL GENIUS

• GMC Member
• 1905 posts
• Version:GM6

Posted 13 May 2010 - 09:34 AM

by post #6 i burst out laughing,
has anyone ever called you guys NERDS?

just messin' ..thnx for all your help in the past
• 0

over the next few years there will be an outbreak of new man-made viruses & diseases.