•      Sign In
• Create Account

# Vector3D - Get the Compass orientation ?

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

6 replies to this topic

### #1jujunosuke  Members   -  Reputation: 188

Like
0Likes
Like

Posted 26 May 2011 - 04:08 AM

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..

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;

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..

### #2scgames  Members   -  Reputation: 2078

Like
1Likes
Like

Posted 26 May 2011 - 06:30 AM

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.

### #3Álvaro  Crossbones+   -  Reputation: 19345

Like
1Likes
Like

Posted 26 May 2011 - 07:25 AM

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).

### #4haegarr  Crossbones+   -  Reputation: 7078

Like
1Likes
Like

Posted 26 May 2011 - 07:34 AM

The method shown in the OP cannot work because in
a . b = |a| * |b| * cos( <a,b> )
the term <a,b> means the angle between directions a and b (and not "from a to 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.

### #5jujunosuke  Members   -  Reputation: 188

Like
0Likes
Like

Posted 26 May 2011 - 06:46 PM

Hi all and thank you very much for taking the time to answer.

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

jyk in the code i wrote :
var dotProduct : int
i just wrote it by heart, but my original code was a float.
var dotProduct : float
.
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, alvaro i will try with atan2 !
In the engine i am using (Unity) the up vector is y.

haegarr 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 !

### #6Álvaro  Crossbones+   -  Reputation: 19345

Like
1Likes
Like

Posted 26 May 2011 - 07:49 PM

I think atan2(x,z)*DEGREES_PER_RADIAN is what you need.

### #7jujunosuke  Members   -  Reputation: 188

Like
0Likes
Like

Posted 27 May 2011 - 05:07 AM

Thanks you so much guys.
After some test in my engine, it looks like it is working perfectly.

Here is my final 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;
}
}


Best regards, and thank you again !

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

PARTNERS