# Vector3D - Get the Compass orientation ?

## Recommended Posts

jujunosuke    188
Hi everyone !

I am looking to find a way to get the Compass orientation of a 3D Vector object. I need a result in degrees from 0 to 360.
The way i could know the orientation of the object.

Here is what i did so far, but it does not seem to work.
I can't understand why..

[code]
var objectForwardVector : Vector3 = object.transform.forward;
var worldForwardVector : Vector3 = object.transform.forward;
objectForwardVector.x = 0;
objectForwardVector.Normalize();
worldForwardVector.Normalize();
var dotProduct : float = (objectForwardVector, worldForwardVector);
return Acos( dotProduct ) /Math.Pi * 180;
[/code]
Right now, the Compass value change when i move my object on the Longitudinal Axis. (whatever the Longitudinal axis, the Compass orientation should be the same).

anyway, it look strange..

Any idea on that ?
Thank you in advance for any help !

Regards.

*'Edit'* changed int to float..

##### Share on other sites
jyk    2094
A couple of things I noticed:

1. If transform.forward returns a unit-length vector, you don't need to normalize worldForwardVector.

2. 'dotProduct' should probably be of a floating-point type rather than an integer.

3. Strictly speaking, you should generally clamp the argument to acos() to the range [-1, 1] to correct for any numerical error.

I'm not sure why .x is being zeroed out or what angle it is exactly that you're measuring, but the first thing I'd try is making 'dotProduct' a float rather than an int, and see if that helps.

##### Share on other sites
alvaro    21246
The arc-cosine of the dot product can only give you an angle from 0 to 180 degrees. What you want to use is atan2(y,x), ignoring the z coordinate (or whatever coordinate is up).

##### Share on other sites
haegarr    7372
The method shown in the OP cannot work because in
[b]a[/b] . [b]b[/b] = |[b]a[/b]| * |[b]b[/b]| * cos( <[b]a[/b],[b]b[/b]> )
the term <[b]a[/b],[b]b[/b]> means the angle between directions [b]a[/b] and [b]b[/b] (and not "from [b]a[/b] to [b]b[/b]"). As such the result must be in [0°,180°] what contradicts the requirement mentioned in the OP. (EDIT: as alvaro has already pointed out during I wrote this.)

Maybe to yield a compass direction the OP wants to map the 3D direction from the reference point to the target point onto a plane, and to measure the angle from a reference direction on the plane to the mapped direction. (That is more or less how a compass works, where the horizontal part of the magnetic vector field is compared to the north arrow on the compass body.) I think that is the reason why the x component is set to 0. But why those dot-product is computed? I have no clue ...

IMHO, with the local-to-global transformation of the reference plane, using e.g. x-z as the plane and its z axis as north arrow, and the position vector of to the target point, the computation of the compass direction may be:
1. Computing the difference vector from the plane's origin (where the compass is located) to the target point; perhaps normalize it.
2. Transform the difference vector into the plane's local space.
3. Use the atan2(...) function with the x and z components to compute the angle, perhaps with a 90° correction if needed.

##### Share on other sites
jujunosuke    188
Hi all and thank you very much for taking the time to answer.

I would like to clear some points : (Please forgive my English)

[b]jyk[/b] in the code i wrote : [code]var dotProduct : int[/code] i just wrote it by heart, but my original code was a float. [code]var dotProduct : float[/code].
So sorry for that mistake !

the wrold X vector was set to 0 to indicate the starting angle (North).
Also, i think that getting values from 0 to 180 are not hard to convert to 360. because, if i go in the North, my Object forward vector would be 0, 0, 1
And if i go to the south it will be 0, 0, -1, so i can say something like, if the result is positive, calculate the first 180 half, and if the result is negative, calculate the other 180 half. In order to get my full 360 circle.

Anyway, [b]alvaro[/b] i will try with atan2 !
In the engine i am using (Unity) the up vector is y.

[b]haegarr[/b] Thank you for writing this, it will help me to understand ! (It is sill hard for be because English is not my first language, so if you add Math on top of that hehe)..

So basically a normalized compass pointing in the North direction should be (0, 0, 1) right ?
Anyway, i will try this tonight and report as soon as possible here.

Thanks again !

##### Share on other sites
alvaro    21246
I think atan2(x,z)*DEGREES_PER_RADIAN is what you need.

##### Share on other sites
jujunosuke    188
Thanks you so much guys.
After some test in my engine, it looks like it is working perfectly.

Here is my final code :

[code]
public function getCompass():Number {
var result : float = Mathf.Atan2(transform.forward.x,transform.forward.z) / Mathf.PI * 180;
if (result > 0) {
return result;
} else {
return 360 + result;
}
}
[/code]

Best regards, and thank you again !