XNA Creators Club Online
Page 1 of 1 (14 items)
Sort Posts: Previous Next

Horizontal and Vertical angles between two 3D Vectors?

Last post 09-05-2008 12:47 PM by mreaves. 13 replies.
  • 02-17-2008 1:11 PM

    Horizontal and Vertical angles between two 3D Vectors?

    Hey Guys,

    It's my first post here, been using XNA for a while now and I am currently in the stage of writing the AI for the enemy ships in my space shooter. I get very confused when it comes to calculating angles in 3D, all the angle math functions such as Atan2 seem to return results which I can't get my head around, I seem to have to make the angle negative and substract 90 degrees from it for it to be accurate. I also need the vertical angle and I don't know how you would work that out. A lot of things I read about calculating the angle between two 3D vectors only seem to return one angle, how can you have one angle between a 3D vector? So far I haven't needed to do any angle calculation and this problem is slowing me down, I would appreciate all the help you guys can give.

    Thanks,

    Oli.

  • 02-17-2008 2:07 PM In reply to

    Re: Horizontal and Vertical angles between two 3D Vectors?

    Zebadee2323:
    A lot of things I read about calculating the angle between two 3D vectors only seem to return one angle, how can you have one angle between a 3D vector?

    Two 3D vectors lie in a plane whose normal is the cross product of them.  The angle between them is the angle between them on the plane.

  • 02-17-2008 4:05 PM In reply to

    Re: Horizontal and Vertical angles between two 3D Vectors?

    two vectors have only have 2 directions to turn to get to each other... clockwise or counter-clockwise around the cross product of the two vectors. You record the smallest of the two as the arccos(a dot b).

    Knowing how far up and over is kinda like finding the phi and theta of two spherical vectors. This is different, this isn't just a record of the angle between it, it is a direction and magnitude; kinda like a vector by definition. In 2D you don't notice that the angle between two vectors isn't a direction and magnitude because you assume the direction since there is only two directions to travel around the same gimbal (an imaginary Z gimbal that sticks into the third dimension).

    If you want direction and magnitude in 3D... you get a rotation which can occur around several gimbals (a vector pointing any direction away from the origin).  Several choices have been given to deduce a direction and magnitude: Euler rotations (pitch, yaw, roll), spherical coordinates (phi, theta, row), and quaternions are the most common in 3D programming. Euler rotations are difficult because you can get locked around each gimbal, spherical coords don't describe the situation enough and are more useful for changing positions, and quaternions bring the two together into one useful set up that rotates around imaginary gimbals to reduce gimbal locks AND can be scaled to allow position change as well.
  • 02-17-2008 5:54 PM In reply to

    Re: Horizontal and Vertical angles between two 3D Vectors?

    Ah ha, I think I understand why there is only one angle now! Thanks.

    For my rotations I am using quaternions, so far I have had no trouble with them however I still have no idea how I can calculate the pitch, yaw and roll my ship needs to have to point at another vector, is it possible to give me an example? Thanks a lot for your help so far. 

    *Update*

    I have now successfully calculated the Horizontal and Vertical angles thanks to you guys however I am now encountering another strange problem...

    My ships movement is based on its forward vector, this vector is being rotated by the quaternion created using the two new angles I have calculated, the strange thing is the ship moves correctly towards its target but the actual ship model itself is going crazy even though it is using the same rotation quaternion that the forward vector is being rotated by. There isn't anything wrong with the way I am drawing my models because my rotation for everything else (such as the players ship) is fine.

    Any Ideas?

  • 02-18-2008 5:16 PM In reply to

    Re: Horizontal and Vertical angles between two 3D Vectors?

    how is it going crazy?

    And how are you putting together the quaternion for the forward vector?

    try this out for finding shortest quaternion arc between two vectors (I wrote it real fast... if it doesn't work let me know and I'll dig up my original code and cross check it):

    public static Quaternion rotationBetween(Vector3 v1, Vector3 v2)
    {
    float d = Vector3.Dot(v1, v2);
    Vector3 axis = Vector3.Cross(v1, v2);
    float qw = (float)Math.Sqrt(v1.Length() * v1.Length() * v2.Length() * v2.Length()) + d;

    Quaternion result;

    if (qw < 0.0001)
    { //180 degree turn, infinite possibilities
    result = new Quaternion(-v1.Z, v1.Y, v1.X, 0);
    return Quaternion.Normalize(result);
    }

    result = new Quaternion(axis.X, axis.Y, axis.Z, qw);
    return Quaternion.Normalize(result);
    }


    make sure you put normalized vectors into the function to get the best result.
  • 02-18-2008 6:43 PM In reply to

    Re: Horizontal and Vertical angles between two 3D Vectors?

    Hi, thanks for your reply.

    I meant going crazy as in looking in different directions at very fast speeds :P

    I tried out your code but the ship seems to smoothly fly off in another direction. However your code did help me create some code of my own which seems to work for some positions, for others Vector3.Dot() will return over 1 or under -1 causing it and angle to become "NaN" and then my ship disappears.

    I don't understand enough about quaternions to be able to work out whats wrong (if this is even a quaternion problem).

    Thanks for your help so far, I really do appreciate it.

     
    float dot, angle;
    Vector3 cross, axis, targetVector;
    targetVector = Vector3.Normalize(Target - Position);
    dot = Vector3.Dot(Forward, targetVector);
    angle = (float)Math.Acos(dot);
    cross = Vector3.Cross(Forward, targetVector);
    axis = Vector3.Normalize(cross);
    RotationQuaternion *= Quaternion.CreateFromAxisAngle(axis, angle);
    RotationQuaternion = Quaternion.Normalize(RotationQuaternion);
    RotationMatrix = Matrix.CreateFromQuaternion(RotationQuaternion);
    Forward = Vector3.TransformNormal(Vector3.Forward, RotationMatrix);
    SetVelocity(Forward * 10000 * elapsed);
     
     
     
     
  • 02-18-2008 7:48 PM In reply to

    Re: Horizontal and Vertical angles between two 3D Vectors?

    I'm guessing RotationMatrix is the matrix that handles the rotation of your model. If this is so you have to understand that quaternions, like vectors, are arbitrary. They only have direction and magnitude in the sense that it is an arbitrary axis to rotate around with some magnitude.

    These quaternions can be moved all over the place and multiplied together to make get a complete rotation. If you set the RotationMatrix to that of the rotation beween two vectors you don't actually get the result. You have to multiple the current rotation to the amount of rotation to add on to it.

    RotationQuat = rotBetween2Vecs * RotationQuat;

    Same thing goes with rotation matrices. This is probably why the ship kept looking in all kinds of different directions. You are transforming you forward vector (the path you are following) which would give a proper result, but you set the rotation of your ship to some arbitrary rotation off of Euler(0,0,0) (facing forward down the -z axis).

    Also why have a seperate Forward Vector when you can just use the forward vector of your ship? After updating the RotationMatrix that gets multiplied into the tranform matrix for your ship your Forward Vector is already updated for you... no need to tranformNormal your Forward vector in the first place.

    Here try this code out:
    Vector3 targetVector = Vector3.Normalize(Target - this.Position);
    Quaternion rotationTo = theQuatRotClass.rotationBetween(RotationMatrix.Forward, targetVector);
    Matrix rotToMatrix = Matrix.CreateFromQuaternion(rotationTo);

    RotationMatrix *= rotToMatrix;

    SetVelocity(RotationMatrix.Forward * 10000 * elapsed);


    you could also create a method for just finding the rotationTo in Matrix form instead of creating it in a Quaternion and converting.

    Oh and your "Quaternion.CreateFromAxisAngle" doesn't know which direction around the axis you are talking about. ArcCos(angle) returns the closest angle between the two vectors, but it doesn't know if said angle is clockwise or counterClockwise from the forward vector. Hence why it probably only works at certain times, but not all (specifically when the target is a clockwise turn from the forward vector).

    Last Edit...
    Keep in mind, Quaternion multiplication AND Matrix multiplication is NOT communicative. This means that a * b != b * a.
  • 02-18-2008 8:40 PM In reply to

    Re: Horizontal and Vertical angles between two 3D Vectors?

    lordofduct:


    Oh and your "Quaternion.CreateFromAxisAngle" doesn't know which direction around the axis you are talking about. ArcCos(angle) returns the closest angle between the two vectors, but it doesn't know if said angle is clockwise or counterClockwise from the forward vector. Hence why it probably only works at certain times, but not all (specifically when the target is a clockwise turn from the forward vector).

    Ah yes that is probably why, I think I have ran into a problem similar to this before, I never managed to work out how to calculate which way an object has to turn to face its target the fastest. I don't know how you would do it only knowing the angle returned from Acos() though.

    Thanks for your help.

  • 02-18-2008 10:07 PM In reply to

    Re: Horizontal and Vertical angles between two 3D Vectors?

    You find the angle between the forward vector and your reference vector to start, that gives you the difference between the two. Then you find the dot product between the right vector and your reference vector, and that number will either be greater than or less than 0. If it is less than zero multiply your angle by -1.
    XNA QuickStart Engine | My site
    "I'll be whatever I want to do!", Philip J. Fry
  • 02-19-2008 3:43 AM In reply to

    Re: Horizontal and Vertical angles between two 3D Vectors?

    Zebadee2323:

    For my rotations I am using quaternions, so far I have had no trouble with them however I still have no idea how I can calculate the pitch, yaw and roll my ship needs to have to point at another vector, is it possible to give me an example? Thanks a lot for your help so far. 

    Any Ideas?

    Here is a different approach to think about.   If you are pointing one ship at a target, this thread will be helpful http://forums.xna.com/thread/32295.aspx as it shows a different (and for me, much simpler) approach.  The post in the thread that is the most relevant is.. http://forums.xna.com/post/32295.aspx

    I have my spaceship world_matrix and a set of quaternions I use for rotations when I update the ship with a controller.  When I want to point the ship at something, I use a variation of the code referenced in the link.   After updating the direciton of the ship (the world_matrix up, forward, and right vectors) using the vector math, I update my quaternions using quaternion.CreateFromRotationMatrix(world_matrix).  

    What I am doing now is keeping a vector3 target which I translate around with the controller and simply pass that target to my "point_at" function when I want to move the ship with the controller.   If the ship acquires a target it needs to approach, I simply drop in the position of that target.

    best,

    Byron

    ..shaders make you feel... powerful, or very very stupid.
    http://drjbn.spaces.live.com/
  • 02-19-2008 5:22 PM In reply to

    Re: Horizontal and Vertical angles between two 3D Vectors?

    Thanks for the great replies guys, I have successfully got my ships flying to their targets :D. I have managed to implement some battle AI too, it's a very strange experience watching your AI fight each other.

    Also just a small off topic question regarding ArrayList performance; I store all the lasers the ships shoot into an ArrayList, when there are a lot of them on screen they seem to "lag" as if I was playing an online game but all my other objects that are not managed by the ArrayList have smooth movement. I was just wondering if ArrayLists run on seperate threads or something and they are not keeping up fast enough with the main loop causing this lag effect? Or am I just talking absolute rubbish? :P

  • 02-19-2008 8:53 PM In reply to