Results 1 to 8 of 8

Thread: XNA: Quaternion from two Vector3s

  1. #1

    Thread Starter
    Lively Member homer13j's Avatar
    Join Date
    Nov 2003
    Location
    Ohio Turnpike Exit 173
    Posts
    80

    XNA: Quaternion from two Vector3s

    Working from the XNA aiming sample and trying to convert it to 3d...

    I have a rotating gun turret that I'm trying to turn to point at a moving ship, but it's not quite working as I expected it to. I'm taking the angle between two Vector3s (representing the turret and ship positions) along each of the 3 axes, create a rotation matrix and generate a quaternion that I can apply to the turret to point it at the ship. Two questions:

    What am I doing wrong?

    Is there an easier way to do this?

    position = turret position
    aimAtThis = ship position

    Code:
            Quaternion Target3D(Vector3 position, Vector3 aimAtThis)
            {
                float x = aimAtThis.X - position.X;
                float y = aimAtThis.Y - position.Y;
                float z = aimAtThis.Z - position.Z;
                float xAngle = WrapAngle((float)Math.Atan2(z, y));
                float yAngle = WrapAngle((float)Math.Atan2(z, x));
                float zAngle = WrapAngle((float)Math.Atan2(y, x));
    
                Matrix m = Matrix.CreateRotationX(xAngle) *
                           Matrix.CreateRotationY(yAngle) *
                           Matrix.CreateRotationZ(zAngle);
                Quaternion q = Quaternion.CreateFromRotationMatrix(m);
    
                return q;
            }
    
            float WrapAngle(float radians)
            {
                while (radians < -MathHelper.Pi)
                {
                    radians += MathHelper.TwoPi;
                }
                while (radians > MathHelper.Pi)
                {
                    radians -= MathHelper.TwoPi;
                }
                return radians;
            }
    Thanks.

  2. #2
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: XNA: Quaternion from two Vector3s

    You say it's not quite working as you expect it to. What is it doing exactly?

    In the meantime, try this code:

    Code:
           private Quaternion GetRotation(Vector3 src, Vector3 dest)
            {
                src.Normalize();
                dest.Normalize();
    
                float d = Vector3.Dot(src, dest);
    
                if (d >= 1f)
                {
                    return Quaternion.Identity;
                }
                else if (d < (1e-6f - 1.0f))
                {
                    Vector3 axis = Vector3.Cross(Vector3.UnitX, src);
    
                    if (axis.LengthSquared() == 0)
                    {
                        axis = Vector3.Cross(Vector3.UnitY, src);
                    }
    
                    axis.Normalize();
                    return Quaternion.CreateFromAxisAngle(axis, MathHelper.Pi);
                }
                else
                {
                    float s = (float)Math.Sqrt((1 + d) * 2);
                    float invS = 1 / s;
    
                    Vector3 c = Vector3.Cross(src, dest);
                    Quaternion q = new Quaternion(invS * c, 0.5f * s);
                    q.Normalize();
    
                    return q;
                }
            }
    Last edited by Jenner; Sep 15th, 2009 at 02:38 PM.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  3. #3

    Thread Starter
    Lively Member homer13j's Avatar
    Join Date
    Nov 2003
    Location
    Ohio Turnpike Exit 173
    Posts
    80

    Re: XNA: Quaternion from two Vector3s

    Quote Originally Posted by Jenner View Post
    You say it's not quite working as you expect it to. What is it doing exactly?
    It's rotating, but nowhere near the way I expected it to.

    I tried your code, but now it does not rotate at all. I guess I need to do more homework...

  4. #4
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: XNA: Quaternion from two Vector3s

    Yea, I've been doing some sample apps as well but I have yet to find a single, clear-cut example of how to do this. The code I found will rotate for me, as long as the source model isn't at position 0,0,0. Then it crashes.

    I can rotate it via vectors alone, but this creates gimble-lock.

    I'll keep poking at it though and see if I can't get it working because I have a similar problem in a game I'm designing too.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  5. #5
    New Member
    Join Date
    Sep 2009
    Posts
    2

    Re: XNA: Quaternion from two Vector3s

    wow progamming game ! i try , i try

  6. #6
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: XNA: Quaternion from two Vector3s

    Ok, best I figure on this problem is this:

    #1) You have to translate the positional vectors to the grid origin (0,0,0) first. If your positional vector of your turret is at 1,2,0 and your ship at 15,32,10, you need to subtract them prior to the rotation: (15,32,10) - (1,2,0) = (14, 30, 10) Use this positional coordinate in your calculation.

    #2) A quaternion needs two things now, an axis of rotation, and an angle. The axis is easy because you have two vectors to work with: The ROTATIONAL vector of the turret (i.e. the vector describing the direction it's pointing, not the vector describing it's position in 3D space) and the POSITIONAL vector of your ship, that you just offset in #1.
    Take the cross product, and you get a new vector that's perpendicular to the two, so you just need: axisVector = Vector3.Cross(turretHeadingVector, shipOffsetPositionVector)

    #3) Now you just need the angle between the two vectors, and this is also simple, take the dot product of the same two vectors and then the acos of that to get the angle: angle = Math.Acos(Vector3.Dot(turretHeadingVector, shipOffsetPositionVector))

    #4) Now, just build your quaternion using the axis, angle method: Quaternion.CreateFromAxisAngle(axisVector, angle)

    The best I can tell, this is the simplest method of doing this. Now, there are some issues you need to know and program around, such as some "0" conditions like if the vectors are 180 degrees apart, but if your turret has a limited field of fire, it won't be tracking objects in that coordinate zone anyways.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  7. #7

    Thread Starter
    Lively Member homer13j's Avatar
    Join Date
    Nov 2003
    Location
    Ohio Turnpike Exit 173
    Posts
    80

    Re: XNA: Quaternion from two Vector3s

    Quote Originally Posted by Jenner View Post
    #1) You have to translate the positional vectors to the grid origin (0,0,0) first. If your positional vector of your turret is at 1,2,0 and your ship at 15,32,10, you need to subtract them prior to the rotation: (15,32,10) - (1,2,0) = (14, 30, 10) Use this positional coordinate in your calculation.
    Okay, that's easy enough:

    Code:
    Vector3 translatedPos = aimAtThis - position;
    Quote Originally Posted by Jenner View Post
    #2) A quaternion needs two things now, an axis of rotation, and an angle. The axis is easy because you have two vectors to work with: The ROTATIONAL vector of the turret (i.e. the vector describing the direction it's pointing, not the vector describing it's position in 3D space) and the POSITIONAL vector of your ship, that you just offset in #1.
    Take the cross product, and you get a new vector that's perpendicular to the two, so you just need: axisVector = Vector3.Cross(turretHeadingVector, shipOffsetPositionVector)
    Here's my problem. How do I get the rotational vector of the turret from the positional vectors of the turret and ship?

  8. #8
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    Re: XNA: Quaternion from two Vector3s

    Yea, that was my problem too. It's more or less a unit-vector, since all you're interested in is it's components. All game-engine systems, when dealing with models have some manner to control position (typically a Vector3), and some manner to control rotation (possibly a rotation matrix or a quaternion or a Vector3 unit vector). Do you know how to get any rotational information from your models and what form it takes?

    See, the POSITIONAL vector of the turret is pointless, since you've translated it to 0, 0, 0 anyways! In fact, ANY object you're trying to figure a rotation about will effectively be at 0, 0, 0. If your turret was pointed straight down the X-axis of your world grid and nowhere else, it would be a ROTATIONAL vector (1, 0, 0); it would never be 0, 0 ,0 though since it can never point nowhere.
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width